blob: 5a0869f837f8597c39b56320f855a36882fe0d9f [file] [log] [blame]
Giovanni Bajo9940aba2012-04-23 00:32:01 +02001#include <string.h>
Giovanni Bajo366dfcb2012-04-25 17:40:47 +02002#include "dnsmasq.h"
3#include "dnssec-crypto.h"
Giovanni Bajo9940aba2012-04-23 00:32:01 +02004#include <openssl/evp.h>
Giovanni Bajo0360a522012-04-27 03:14:15 +02005#include <openssl/rsa.h>
Giovanni Bajo9940aba2012-04-23 00:32:01 +02006
Giovanni Bajo366dfcb2012-04-25 17:40:47 +02007typedef struct VACTX_rsasha1
Giovanni Bajo9940aba2012-04-23 00:32:01 +02008{
Giovanni Bajo366dfcb2012-04-25 17:40:47 +02009 VerifyAlgCtx base;
10 unsigned char *sig;
11 unsigned siglen;
12 union
13 {
14 EVP_MD_CTX hash;
15 unsigned char digest[20];
16 };
17} VACTX_rsasha1;
18
19typedef struct VACTX_rsasha256
20{
21 VerifyAlgCtx base;
22 unsigned char *sig;
23 unsigned siglen;
Giovanni Bajo9940aba2012-04-23 00:32:01 +020024 union
25 {
26 EVP_MD_CTX hash;
Giovanni Bajob573aeb2012-04-24 02:21:50 +020027 unsigned char digest[32];
Giovanni Bajo9940aba2012-04-23 00:32:01 +020028 };
Giovanni Bajo366dfcb2012-04-25 17:40:47 +020029} VACTX_rsasha256;
Giovanni Bajo9940aba2012-04-23 00:32:01 +020030
Giovanni Bajo366dfcb2012-04-25 17:40:47 +020031#define POOL_SIZE 1
32static union _Pool
Giovanni Bajo9940aba2012-04-23 00:32:01 +020033{
Giovanni Bajo366dfcb2012-04-25 17:40:47 +020034 VACTX_rsasha1 rsasha1;
35 VACTX_rsasha256 rsasha256;
36} Pool[POOL_SIZE];
37static char pool_used = 0;
38
Giovanni Bajo4e076d72012-04-27 03:24:12 +020039static void print_hex(unsigned char *data, unsigned len)
40{
41 while (len > 0)
42 {
43 printf("%02x", *data++);
44 --len;
45 }
46 printf("\n");
47}
48
Giovanni Bajo366dfcb2012-04-25 17:40:47 +020049static int rsasha1_set_signature(VerifyAlgCtx *ctx_, unsigned char *data, unsigned len)
50{
51 VACTX_rsasha1 *ctx = (VACTX_rsasha1 *)ctx_;
52 ctx->sig = data;
53 ctx->siglen = len;
Giovanni Bajob573aeb2012-04-24 02:21:50 +020054 return 1;
55}
56
Giovanni Bajo366dfcb2012-04-25 17:40:47 +020057static int rsasha256_set_signature(VerifyAlgCtx *ctx_, unsigned char *data, unsigned len)
Giovanni Bajob573aeb2012-04-24 02:21:50 +020058{
Giovanni Bajo366dfcb2012-04-25 17:40:47 +020059 VACTX_rsasha256 *ctx = (VACTX_rsasha256 *)ctx_;
60 ctx->sig = data;
61 ctx->siglen = len;
Giovanni Bajo9940aba2012-04-23 00:32:01 +020062 return 1;
63}
64
Giovanni Bajo366dfcb2012-04-25 17:40:47 +020065static void rsasha1_begin_data(VerifyAlgCtx *ctx_)
Giovanni Bajo9940aba2012-04-23 00:32:01 +020066{
Giovanni Bajo366dfcb2012-04-25 17:40:47 +020067 VACTX_rsasha1 *ctx = (VACTX_rsasha1 *)ctx_;
68 EVP_MD_CTX_init(&ctx->hash);
69 EVP_DigestInit_ex(&ctx->hash, EVP_sha1(), NULL);
Giovanni Bajob573aeb2012-04-24 02:21:50 +020070}
Giovanni Bajo366dfcb2012-04-25 17:40:47 +020071static void rsasha256_begin_data(VerifyAlgCtx *ctx_)
Giovanni Bajob573aeb2012-04-24 02:21:50 +020072{
Giovanni Bajo366dfcb2012-04-25 17:40:47 +020073 VACTX_rsasha256 *ctx = (VACTX_rsasha256 *)ctx_;
74 EVP_MD_CTX_init(&ctx->hash);
75 EVP_DigestInit_ex(&ctx->hash, EVP_sha256(), NULL);
Giovanni Bajo9940aba2012-04-23 00:32:01 +020076}
77
Giovanni Bajo366dfcb2012-04-25 17:40:47 +020078static void rsasha1_add_data(VerifyAlgCtx *ctx_, void *data, unsigned len)
Giovanni Bajo9940aba2012-04-23 00:32:01 +020079{
Giovanni Bajo366dfcb2012-04-25 17:40:47 +020080 VACTX_rsasha1 *ctx = (VACTX_rsasha1 *)ctx_;
81 EVP_DigestUpdate(&ctx->hash, data, len);
Giovanni Bajob573aeb2012-04-24 02:21:50 +020082}
Giovanni Bajo366dfcb2012-04-25 17:40:47 +020083static void rsasha256_add_data(VerifyAlgCtx *ctx_, void *data, unsigned len)
Giovanni Bajob573aeb2012-04-24 02:21:50 +020084{
Giovanni Bajo366dfcb2012-04-25 17:40:47 +020085 VACTX_rsasha256 *ctx = (VACTX_rsasha256 *)ctx_;
86 EVP_DigestUpdate(&ctx->hash, data, len);
Giovanni Bajo9940aba2012-04-23 00:32:01 +020087}
88
Giovanni Bajo366dfcb2012-04-25 17:40:47 +020089static void rsasha1_end_data(VerifyAlgCtx *ctx_)
Giovanni Bajo9940aba2012-04-23 00:32:01 +020090{
Giovanni Bajo366dfcb2012-04-25 17:40:47 +020091 VACTX_rsasha1 *ctx = (VACTX_rsasha1 *)ctx_;
Giovanni Bajo9940aba2012-04-23 00:32:01 +020092 unsigned char digest[20];
Giovanni Bajo366dfcb2012-04-25 17:40:47 +020093 EVP_DigestFinal(&ctx->hash, digest, NULL);
94 memcpy(ctx->digest, digest, 20);
Giovanni Bajob573aeb2012-04-24 02:21:50 +020095}
Giovanni Bajo366dfcb2012-04-25 17:40:47 +020096static void rsasha256_end_data(VerifyAlgCtx *ctx_)
Giovanni Bajob573aeb2012-04-24 02:21:50 +020097{
Giovanni Bajo366dfcb2012-04-25 17:40:47 +020098 VACTX_rsasha256 *ctx = (VACTX_rsasha256 *)ctx_;
Giovanni Bajob573aeb2012-04-24 02:21:50 +020099 unsigned char digest[32];
Giovanni Bajo366dfcb2012-04-25 17:40:47 +0200100 EVP_DigestFinal(&ctx->hash, digest, NULL);
101 memcpy(ctx->digest, digest, 32);
Giovanni Bajo9940aba2012-04-23 00:32:01 +0200102}
103
Giovanni Bajo0360a522012-04-27 03:14:15 +0200104static int keydata_to_bn(BIGNUM *ret, struct keydata **key_data, unsigned char **p, unsigned len)
105{
106 size_t cnt;
107 BIGNUM temp;
108
109 BN_init(ret);
110
111 cnt = keydata_walk(key_data, p, len);
112 BN_bin2bn(*p, cnt, ret);
113 len -= cnt;
114 *p += cnt;
115 while (len > 0)
116 {
117 if (!(cnt = keydata_walk(key_data, p, len)))
118 return 0;
119 BN_lshift(ret, ret, cnt*8);
120 BN_init(&temp);
121 BN_bin2bn(*p, cnt, &temp);
122 BN_add(ret, ret, &temp);
123 len -= cnt;
124 *p += cnt;
125 }
126 return 1;
127}
128
129static int rsasha1_parse_key(BIGNUM *exp, BIGNUM *mod, struct keydata *key_data, unsigned key_len)
130{
131 unsigned char *p = key_data->key;
132 size_t exp_len, mod_len;
133
134 CHECKED_GETCHAR(exp_len, p, key_len);
135 if (exp_len == 0)
136 CHECKED_GETSHORT(exp_len, p, key_len);
137 if (exp_len >= key_len)
138 return 0;
139 mod_len = key_len - exp_len;
140
141 return keydata_to_bn(exp, &key_data, &p, exp_len) &&
142 keydata_to_bn(mod, &key_data, &p, mod_len);
143}
144
Giovanni Bajo262ac852012-04-27 03:13:34 +0200145static int rsasha1_verify(VerifyAlgCtx *ctx_, struct keydata *key_data, unsigned key_len)
Giovanni Bajo9940aba2012-04-23 00:32:01 +0200146{
Giovanni Bajo366dfcb2012-04-25 17:40:47 +0200147 VACTX_rsasha1 *ctx = (VACTX_rsasha1 *)ctx_;
Giovanni Bajo0360a522012-04-27 03:14:15 +0200148 int validated = 0;
149
150 printf("OpenSSL RSA verification\n");
151 RSA *rsa = RSA_new();
152 rsa->e = BN_new();
153 rsa->n = BN_new();
154
155 if (rsasha1_parse_key(rsa->e, rsa->n, key_data, key_len)
156 && RSA_verify(NID_sha1, ctx->digest, 20, ctx->sig, ctx->siglen, rsa))
157 validated = 1;
158
159 RSA_free(rsa);
160 return validated;
Giovanni Bajo9940aba2012-04-23 00:32:01 +0200161}
162
Giovanni Bajo262ac852012-04-27 03:13:34 +0200163static int rsasha256_verify(VerifyAlgCtx *ctx_, struct keydata *key, unsigned key_len)
Giovanni Bajob573aeb2012-04-24 02:21:50 +0200164{
Giovanni Bajo366dfcb2012-04-25 17:40:47 +0200165 VACTX_rsasha256 *ctx = (VACTX_rsasha256 *)ctx_;
Giovanni Bajob573aeb2012-04-24 02:21:50 +0200166 return 0;
167}
168
Giovanni Bajo366dfcb2012-04-25 17:40:47 +0200169#define DEFINE_VALG(alg) \
170 int alg ## _set_signature(VerifyAlgCtx *ctx, unsigned char *data, unsigned len); \
171 void alg ## _begin_data(VerifyAlgCtx *ctx); \
172 void alg ## _add_data(VerifyAlgCtx *ctx, void *data, unsigned len); \
173 void alg ## _end_data(VerifyAlgCtx *ctx); \
Giovanni Bajo262ac852012-04-27 03:13:34 +0200174 int alg ## _verify(VerifyAlgCtx *ctx, struct keydata *key, unsigned key_len) \
Giovanni Bajo366dfcb2012-04-25 17:40:47 +0200175 /**/
176
177#define VALG_VTABLE(alg) { \
178 alg ## _set_signature, \
179 alg ## _begin_data, \
180 alg ## _add_data, \
181 alg ## _end_data, \
182 alg ## _verify \
183 } /**/
184
185DEFINE_VALG(rsasha1);
186DEFINE_VALG(rsasha256);
187
188/* Updated registry that merges various RFCs:
189 https://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xml */
190static const VerifyAlg valgs[] =
191{
192 {0,0,0,0,0}, /* 0: reserved */
193 {0,0,0,0,0}, /* 1: RSAMD5 */
194 {0,0,0,0,0}, /* 2: DH */
195 {0,0,0,0,0}, /* 3: DSA */
196 {0,0,0,0,0}, /* 4: ECC */
197 VALG_VTABLE(rsasha1), /* 5: RSASHA1 */
198 {0,0,0,0,0}, /* 6: DSA-NSEC3-SHA1 */
199 {0,0,0,0,0}, /* 7: RSASHA1-NSEC3-SHA1 */
200 VALG_VTABLE(rsasha256), /* 8: RSASHA256 */
201 {0,0,0,0,0}, /* 9: unassigned */
202 {0,0,0,0,0}, /* 10: RSASHA512 */
203 {0,0,0,0,0}, /* 11: unassigned */
204 {0,0,0,0,0}, /* 12: ECC-GOST */
205 {0,0,0,0,0}, /* 13: ECDSAP256SHA256 */
206 {0,0,0,0,0}, /* 14: ECDSAP384SHA384 */
207};
208
209static const int valgctx_size[] =
210{
211 0, /* 0: reserved */
212 0, /* 1: RSAMD5 */
213 0, /* 2: DH */
214 0, /* 3: DSA */
215 0, /* 4: ECC */
216 sizeof(VACTX_rsasha1), /* 5: RSASHA1 */
217 0, /* 6: DSA-NSEC3-SHA1 */
218 0, /* 7: RSASHA1-NSEC3-SHA1 */
219 sizeof(VACTX_rsasha256), /* 8: RSASHA256 */
220 0, /* 9: unassigned */
221 0, /* 10: RSASHA512 */
222 0, /* 11: unassigned */
223 0, /* 12: ECC-GOST */
224 0, /* 13: ECDSAP256SHA256 */
225 0, /* 14: ECDSAP384SHA384 */
226};
227
228int verifyalg_supported(int algo)
229{
230 return (algo < countof(valgctx_size) && valgctx_size[algo] != 0);
231}
232
233VerifyAlgCtx* verifyalg_alloc(int algo)
234{
235 int i;
236 VerifyAlgCtx *ret = 0;
237
238 if (!verifyalg_supported(algo))
239 return 0;
240
241 if (pool_used == (1<<POOL_SIZE)-1)
242 ret = whine_malloc(valgctx_size[algo]);
243 else
244 for (i = 0; i < POOL_SIZE; ++i)
245 if (!(pool_used & (1 << i)))
246 {
Giovanni Bajo776fd042012-04-26 14:37:10 +0200247 ret = (VerifyAlgCtx*)&Pool[i];
Giovanni Bajo366dfcb2012-04-25 17:40:47 +0200248 pool_used |= 1 << i;
249 break;
250 }
251
252 if (ret)
253 ret->vtbl = &valgs[algo];
254 return ret;
255}
256
257void verifyalg_free(VerifyAlgCtx *a)
258{
259 int pool_idx = ((char*)a - (char*)&Pool[0]) / sizeof(Pool[0]);
260 if (pool_idx < 0 || pool_idx >= POOL_SIZE)
261 {
262 free(a);
263 return;
264 }
265
266 pool_used &= ~(1 << pool_idx);
267}
Giovanni Bajo6759b992012-04-25 18:03:24 +0200268
269int verifyalg_algonum(VerifyAlgCtx *a)
270{
271 int num = a->vtbl - valgs;
272 if (num < 0 || num >= countof(valgs))
273 return -1;
274 return num;
275}