2 * Copyright (C) 2011-2012 Free Software Foundation, Inc.
4 * Author: Nikos Mavrogiannopoulos
6 * This file is part of GnuTLS.
8 * The GnuTLS is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public License
10 * as published by the Free Software Foundation; either version 3 of
11 * the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful, but
14 * WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>
23 #include <gnutls_int.h>
24 #include <algorithms.h>
25 #include <gnutls_errors.h>
26 #include <x509/common.h>
28 /* signature algorithms;
30 struct gnutls_sign_entry
34 gnutls_sign_algorithm_t id
;
35 gnutls_pk_algorithm_t pk
;
36 gnutls_digest_algorithm_t mac
;
37 /* See RFC 5246 HashAlgorithm and SignatureAlgorithm
38 for values to use in aid struct. */
39 const sign_algorithm_st aid
;
41 typedef struct gnutls_sign_entry gnutls_sign_entry
;
43 #define TLS_SIGN_AID_UNKNOWN {255, 255}
44 static const sign_algorithm_st unknown_tls_aid
= TLS_SIGN_AID_UNKNOWN
;
46 static const gnutls_sign_entry sign_algorithms
[] = {
47 {"RSA-SHA1", SIG_RSA_SHA1_OID
, GNUTLS_SIGN_RSA_SHA1
, GNUTLS_PK_RSA
,
48 GNUTLS_DIG_SHA1
, {2, 1}},
49 {"RSA-SHA224", SIG_RSA_SHA224_OID
, GNUTLS_SIGN_RSA_SHA224
, GNUTLS_PK_RSA
,
50 GNUTLS_DIG_SHA224
, {3, 1}},
51 {"RSA-SHA256", SIG_RSA_SHA256_OID
, GNUTLS_SIGN_RSA_SHA256
, GNUTLS_PK_RSA
,
52 GNUTLS_DIG_SHA256
, {4, 1}},
53 {"RSA-SHA384", SIG_RSA_SHA384_OID
, GNUTLS_SIGN_RSA_SHA384
, GNUTLS_PK_RSA
,
54 GNUTLS_DIG_SHA384
, {5, 1}},
55 {"RSA-SHA512", SIG_RSA_SHA512_OID
, GNUTLS_SIGN_RSA_SHA512
, GNUTLS_PK_RSA
,
56 GNUTLS_DIG_SHA512
, {6, 1}},
57 {"RSA-RMD160", SIG_RSA_RMD160_OID
, GNUTLS_SIGN_RSA_RMD160
, GNUTLS_PK_RSA
,
58 GNUTLS_DIG_RMD160
, TLS_SIGN_AID_UNKNOWN
},
59 {"DSA-SHA1", SIG_DSA_SHA1_OID
, GNUTLS_SIGN_DSA_SHA1
, GNUTLS_PK_DSA
,
60 GNUTLS_DIG_SHA1
, {2, 2}},
61 {"DSA-SHA224", SIG_DSA_SHA224_OID
, GNUTLS_SIGN_DSA_SHA224
, GNUTLS_PK_DSA
,
62 GNUTLS_DIG_SHA224
, {3, 2}},
63 {"DSA-SHA256", SIG_DSA_SHA256_OID
, GNUTLS_SIGN_DSA_SHA256
, GNUTLS_PK_DSA
,
64 GNUTLS_DIG_SHA256
, {4, 2}},
65 {"RSA-MD5", SIG_RSA_MD5_OID
, GNUTLS_SIGN_RSA_MD5
, GNUTLS_PK_RSA
,
66 GNUTLS_DIG_MD5
, {1, 1}},
67 {"RSA-MD2", SIG_RSA_MD2_OID
, GNUTLS_SIGN_RSA_MD2
, GNUTLS_PK_RSA
,
68 GNUTLS_DIG_MD2
, TLS_SIGN_AID_UNKNOWN
},
69 {"ECDSA-SHA1", "1.2.840.10045.4.1", GNUTLS_SIGN_ECDSA_SHA1
, GNUTLS_PK_EC
, GNUTLS_DIG_SHA1
, {2, 3}},
70 {"ECDSA-SHA224", "1.2.840.10045.4.3.1", GNUTLS_SIGN_ECDSA_SHA224
, GNUTLS_PK_EC
, GNUTLS_DIG_SHA224
, {3, 3}},
71 {"ECDSA-SHA256", "1.2.840.10045.4.3.2", GNUTLS_SIGN_ECDSA_SHA256
, GNUTLS_PK_EC
, GNUTLS_DIG_SHA256
, {4, 3}},
72 {"ECDSA-SHA384", "1.2.840.10045.4.3.3", GNUTLS_SIGN_ECDSA_SHA384
, GNUTLS_PK_EC
, GNUTLS_DIG_SHA384
, {5, 3}},
73 {"ECDSA-SHA512", "1.2.840.10045.4.3.4", GNUTLS_SIGN_ECDSA_SHA512
, GNUTLS_PK_EC
, GNUTLS_DIG_SHA512
, {6, 3}},
74 {"GOST R 34.10-2001", SIG_GOST_R3410_2001_OID
, 0, 0, 0,
75 TLS_SIGN_AID_UNKNOWN
},
76 {"GOST R 34.10-94", SIG_GOST_R3410_94_OID
, 0, 0, 0, TLS_SIGN_AID_UNKNOWN
},
77 {0, 0, 0, 0, 0, TLS_SIGN_AID_UNKNOWN
}
80 #define GNUTLS_SIGN_LOOP(b) \
82 const gnutls_sign_entry *p; \
83 for(p = sign_algorithms; p->name != NULL; p++) { b ; } \
86 #define GNUTLS_SIGN_ALG_LOOP(a) \
87 GNUTLS_SIGN_LOOP( if(p->id && p->id == sign) { a; break; } )
90 * gnutls_sign_get_name:
91 * @algorithm: is a sign algorithm
93 * Convert a #gnutls_sign_algorithm_t value to a string.
95 * Returns: a string that contains the name of the specified sign
96 * algorithm, or %NULL.
99 gnutls_sign_get_name (gnutls_sign_algorithm_t algorithm
)
101 gnutls_sign_algorithm_t sign
= algorithm
;
102 const char *ret
= NULL
;
105 GNUTLS_SIGN_ALG_LOOP (ret
= p
->name
);
111 * gnutls_sign_is_secure:
112 * @algorithm: is a sign algorithm
114 * Returns: Non-zero if the provided signature algorithm is considered to be secure.
117 gnutls_sign_is_secure (gnutls_sign_algorithm_t algorithm
)
119 gnutls_sign_algorithm_t sign
= algorithm
;
120 gnutls_digest_algorithm_t dig
= GNUTLS_DIG_UNKNOWN
;
123 GNUTLS_SIGN_ALG_LOOP (dig
= p
->mac
);
125 if (dig
!= GNUTLS_DIG_UNKNOWN
)
126 return _gnutls_digest_is_secure(dig
);
134 * Get a list of supported public key signature algorithms.
136 * Returns: a (0)-terminated list of #gnutls_sign_algorithm_t
137 * integers indicating the available ciphers.
140 const gnutls_sign_algorithm_t
*
141 gnutls_sign_list (void)
143 static gnutls_sign_algorithm_t supported_sign
[MAX_ALGOS
] = {0};
145 if (supported_sign
[0] == 0)
149 GNUTLS_SIGN_LOOP (supported_sign
[i
++]=p
->id
);
150 supported_sign
[i
++]=0;
153 return supported_sign
;
157 * gnutls_sign_get_id:
158 * @name: is a sign algorithm name
160 * The names are compared in a case insensitive way.
162 * Returns: return a #gnutls_sign_algorithm_t value corresponding to
163 * the specified algorithm, or %GNUTLS_SIGN_UNKNOWN on error.
165 gnutls_sign_algorithm_t
166 gnutls_sign_get_id (const char *name
)
168 gnutls_sign_algorithm_t ret
= GNUTLS_SIGN_UNKNOWN
;
171 if (strcasecmp (p
->name
, name
) == 0)
182 gnutls_sign_algorithm_t
183 _gnutls_x509_oid2sign_algorithm (const char *oid
)
185 gnutls_sign_algorithm_t ret
= 0;
187 GNUTLS_SIGN_LOOP (if (p
->oid
&& strcmp (oid
, p
->oid
) == 0)
196 _gnutls_debug_log ("Unknown SIGN OID: '%s'\n", oid
);
197 return GNUTLS_SIGN_UNKNOWN
;
204 * @pk: is a public key algorithm
205 * @hash: a hash algorithm
207 * This function maps public key and hash algorithms combinations
208 * to signature algorithms.
210 * Returns: return a #gnutls_sign_algorithm_t value, or %GNUTLS_SIGN_UNKNOWN on error.
212 gnutls_sign_algorithm_t
213 gnutls_pk_to_sign (gnutls_pk_algorithm_t pk
, gnutls_digest_algorithm_t hash
)
215 gnutls_sign_algorithm_t ret
= 0;
217 GNUTLS_SIGN_LOOP (if (pk
== p
->pk
&& hash
== p
->mac
)
223 return GNUTLS_SIGN_UNKNOWN
;
228 _gnutls_x509_sign_to_oid (gnutls_pk_algorithm_t pk
,
229 gnutls_digest_algorithm_t mac
)
231 gnutls_sign_algorithm_t sign
;
232 const char *ret
= NULL
;
234 sign
= gnutls_pk_to_sign (pk
, mac
);
235 if (sign
== GNUTLS_SIGN_UNKNOWN
)
238 GNUTLS_SIGN_ALG_LOOP (ret
= p
->oid
);
243 * gnutls_sign_get_hash_algorithm:
244 * @sign: is a signature algorithm
246 * This function returns the digest algorithm corresponding to
247 * the given signature algorithms.
251 * Returns: return a #gnutls_digest_algorithm_t value, or %GNUTLS_DIG_UNKNOWN on error.
253 gnutls_digest_algorithm_t
254 gnutls_sign_get_hash_algorithm (gnutls_sign_algorithm_t sign
)
256 gnutls_digest_algorithm_t ret
= GNUTLS_DIG_UNKNOWN
;
258 GNUTLS_SIGN_ALG_LOOP (ret
= p
->mac
);
264 * gnutls_sign_get_pk_algorithm:
265 * @sign: is a signature algorithm
267 * This function returns the public key algorithm corresponding to
268 * the given signature algorithms.
272 * Returns: return a #gnutls_pk_algorithm_t value, or %GNUTLS_PK_UNKNOWN on error.
274 gnutls_pk_algorithm_t
275 gnutls_sign_get_pk_algorithm (gnutls_sign_algorithm_t sign
)
277 gnutls_pk_algorithm_t ret
= GNUTLS_PK_UNKNOWN
;
279 GNUTLS_SIGN_ALG_LOOP (ret
= p
->pk
);
284 gnutls_sign_algorithm_t
285 _gnutls_tls_aid_to_sign (const sign_algorithm_st
* aid
)
287 gnutls_sign_algorithm_t ret
= GNUTLS_SIGN_UNKNOWN
;
289 if (memcmp(aid
, &unknown_tls_aid
, sizeof(*aid
))==0)
292 GNUTLS_SIGN_LOOP (if (p
->aid
.hash_algorithm
== aid
->hash_algorithm
293 && p
->aid
.sign_algorithm
== aid
->sign_algorithm
)
303 /* Returns NULL if a valid AID is not found
305 const sign_algorithm_st
*
306 _gnutls_sign_to_tls_aid (gnutls_sign_algorithm_t sign
)
308 const sign_algorithm_st
* ret
= NULL
;
310 GNUTLS_SIGN_ALG_LOOP (ret
= &p
->aid
);
312 if (ret
!= NULL
&& memcmp(ret
, &unknown_tls_aid
, sizeof(*ret
))==0)