Add explicit digest mapping functions (for OCSP).
[gnutls:gnutls.git] / lib / algorithms / mac.c
1 /*
2  * Copyright (C) 2011 Free Software Foundation, Inc.
3  *
4  * Author: Nikos Mavrogiannopoulos
5  *
6  * This file is part of GnuTLS.
7  *
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.
12  *
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.
17  *
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/>
20  *
21  */
22
23 #include <gnutls_int.h>
24 #include <algorithms.h>
25 #include <gnutls_errors.h>
26 #include <x509/common.h>
27
28 struct gnutls_hash_entry
29 {
30   const char *name;
31   const char *oid;
32   gnutls_mac_algorithm_t id;
33   size_t key_size;              /* in case of mac */
34 };
35 typedef struct gnutls_hash_entry gnutls_hash_entry;
36
37 static const gnutls_hash_entry hash_algorithms[] = {
38   {"SHA1", HASH_OID_SHA1, GNUTLS_MAC_SHA1, 20},
39   {"MD5", HASH_OID_MD5, GNUTLS_MAC_MD5, 16},
40   {"SHA256", HASH_OID_SHA256, GNUTLS_MAC_SHA256, 32},
41   {"SHA384", HASH_OID_SHA384, GNUTLS_MAC_SHA384, 48},
42   {"SHA512", HASH_OID_SHA512, GNUTLS_MAC_SHA512, 64},
43   {"SHA224", HASH_OID_SHA224, GNUTLS_MAC_SHA224, 28},
44   {"AEAD", NULL, GNUTLS_MAC_AEAD, 0},
45   {"MD2", HASH_OID_MD2, GNUTLS_MAC_MD2, 0},     /* not used as MAC */
46   {"RIPEMD160", HASH_OID_RMD160, GNUTLS_MAC_RMD160, 20},
47   {"MAC-NULL", NULL, GNUTLS_MAC_NULL, 0},
48   {0, 0, 0, 0}
49 };
50
51
52 #define GNUTLS_HASH_LOOP(b) \
53         const gnutls_hash_entry *p; \
54                 for(p = hash_algorithms; p->name != NULL; p++) { b ; }
55
56 #define GNUTLS_HASH_ALG_LOOP(a) \
57                         GNUTLS_HASH_LOOP( if(p->id == algorithm) { a; break; } )
58
59 int
60 _gnutls_mac_priority (gnutls_session_t session,
61                       gnutls_mac_algorithm_t algorithm)
62 {                               /* actually returns the priority */
63   unsigned int i;
64   for (i = 0; i < session->internals.priorities.mac.algorithms; i++)
65     {
66       if (session->internals.priorities.mac.priority[i] == algorithm)
67         return i;
68     }
69   return -1;
70 }
71
72 /**
73  * gnutls_mac_get_name:
74  * @algorithm: is a MAC algorithm
75  *
76  * Convert a #gnutls_mac_algorithm_t value to a string.
77  *
78  * Returns: a string that contains the name of the specified MAC
79  *   algorithm, or %NULL.
80  **/
81 const char *
82 gnutls_mac_get_name (gnutls_mac_algorithm_t algorithm)
83 {
84   const char *ret = NULL;
85
86   /* avoid prefix */
87   GNUTLS_HASH_ALG_LOOP (ret = p->name);
88
89   return ret;
90 }
91
92 /**
93  * gnutls_mac_get_id:
94  * @name: is a MAC algorithm name
95  *
96  * Convert a string to a #gnutls_mac_algorithm_t value.  The names are
97  * compared in a case insensitive way.
98  *
99  * Returns: a #gnutls_mac_algorithm_t id of the specified MAC
100  *   algorithm string, or %GNUTLS_MAC_UNKNOWN on failures.
101  **/
102 gnutls_mac_algorithm_t
103 gnutls_mac_get_id (const char *name)
104 {
105   gnutls_mac_algorithm_t ret = GNUTLS_MAC_UNKNOWN;
106
107   GNUTLS_HASH_LOOP (
108     if (strcasecmp (p->name, name) == 0) 
109       {
110         ret = p->id;
111         break;
112       }
113   );
114
115   return ret;
116 }
117
118 /**
119  * gnutls_mac_get_key_size:
120  * @algorithm: is an encryption algorithm
121  *
122  * Get size of MAC key.
123  *
124  * Returns: length (in bytes) of the given MAC key size, or 0 if the
125  *   given MAC algorithm is invalid.
126  **/
127 size_t
128 gnutls_mac_get_key_size (gnutls_mac_algorithm_t algorithm)
129 {
130   size_t ret = 0;
131
132   /* avoid prefix */
133   GNUTLS_HASH_ALG_LOOP (ret = p->key_size);
134
135   return ret;
136 }
137
138 /**
139  * gnutls_mac_list:
140  *
141  * Get a list of hash algorithms for use as MACs.  Note that not
142  * necessarily all MACs are supported in TLS cipher suites.  For
143  * example, MD2 is not supported as a cipher suite, but is supported
144  * for other purposes (e.g., X.509 signature verification or similar).
145  *
146  * This function is not thread safe.
147  *
148  * Returns: Return a (0)-terminated list of #gnutls_mac_algorithm_t
149  *   integers indicating the available MACs.
150  **/
151 const gnutls_mac_algorithm_t *
152 gnutls_mac_list (void)
153 {
154 static gnutls_mac_algorithm_t supported_macs[MAX_ALGOS] = { 0 };
155
156   if (supported_macs[0] == 0)
157     {
158       int i = 0;
159
160       GNUTLS_HASH_LOOP ( supported_macs[i++]=p->id);
161       supported_macs[i++]=0;
162     }
163
164   return supported_macs;
165 }
166
167 const char *
168 _gnutls_x509_mac_to_oid (gnutls_mac_algorithm_t algorithm)
169 {
170   const char *ret = NULL;
171
172   /* avoid prefix */
173   GNUTLS_HASH_ALG_LOOP (ret = p->oid);
174
175   return ret;
176 }
177
178 gnutls_mac_algorithm_t
179 _gnutls_x509_oid2mac_algorithm (const char *oid)
180 {
181   gnutls_mac_algorithm_t ret = 0;
182
183   GNUTLS_HASH_LOOP (if (p->oid && strcmp (oid, p->oid) == 0)
184                     {
185                     ret = p->id; break;}
186   );
187
188   if (ret == 0)
189     return GNUTLS_MAC_UNKNOWN;
190   return ret;
191 }
192
193 const char *
194 _gnutls_x509_digest_to_oid (gnutls_digest_algorithm_t algorithm)
195 {
196   return _gnutls_x509_mac_to_oid ((gnutls_mac_algorithm_t) algorithm);
197 }
198
199 gnutls_digest_algorithm_t
200 _gnutls_x509_oid2digest_algorithm (const char *oid)
201 {
202   return (gnutls_digest_algorithm_t) _gnutls_x509_oid2mac_algorithm (oid);
203 }
204
205 const char *
206 _gnutls_digest_get_name (gnutls_digest_algorithm_t algorithm)
207 {
208   return gnutls_mac_get_name ((gnutls_digest_algorithm_t) algorithm);
209 }
210
211 int
212 _gnutls_mac_is_ok (gnutls_mac_algorithm_t algorithm)
213 {
214   ssize_t ret = -1;
215   GNUTLS_HASH_ALG_LOOP (ret = p->id);
216   if (ret >= 0)
217     ret = 0;
218   else
219     ret = 1;
220   return ret;
221 }