/src/opensc/openpace/src/eac_util.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright (c) 2010-2012 Frank Morgner and Dominik Oepen |
3 | | * |
4 | | * This file is part of OpenPACE. |
5 | | * |
6 | | * OpenPACE is free software: you can redistribute it and/or modify it under |
7 | | * the terms of the GNU General Public License as published by the Free |
8 | | * Software Foundation, either version 3 of the License, or (at your option) |
9 | | * any later version. |
10 | | * |
11 | | * OpenPACE is distributed in the hope that it will be useful, but WITHOUT ANY |
12 | | * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS |
13 | | * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more |
14 | | * details. |
15 | | * |
16 | | * You should have received a copy of the GNU General Public License along with |
17 | | * OpenPACE. If not, see <http://www.gnu.org/licenses/>. |
18 | | * |
19 | | * Additional permission under GNU GPL version 3 section 7 |
20 | | * |
21 | | * If you modify this Program, or any covered work, by linking or combining it |
22 | | * with OpenSSL (or a modified version of that library), containing |
23 | | * parts covered by the terms of OpenSSL's license, the licensors of |
24 | | * this Program grant you additional permission to convey the resulting work. |
25 | | * Corresponding Source for a non-source form of such a combination shall include |
26 | | * the source code for the parts of OpenSSL used as well as that of the |
27 | | * covered work. |
28 | | * |
29 | | * If you modify this Program, or any covered work, by linking or combining it |
30 | | * with OpenSC (or a modified version of that library), containing |
31 | | * parts covered by the terms of OpenSC's license, the licensors of |
32 | | * this Program grant you additional permission to convey the resulting work. |
33 | | * Corresponding Source for a non-source form of such a combination shall include |
34 | | * the source code for the parts of OpenSC used as well as that of the |
35 | | * covered work. |
36 | | */ |
37 | | |
38 | | /** |
39 | | * @file eac_util.c |
40 | | * @brief Utility functions |
41 | | * |
42 | | * @author Frank Morgner <frankmorgner@gmail.com> |
43 | | * @author Dominik Oepen <oepen@informatik.hu-berlin.de> |
44 | | */ |
45 | | |
46 | | #ifdef HAVE_CONFIG_H |
47 | | #include "config.h" |
48 | | #endif |
49 | | |
50 | | #include "eac_asn1.h" |
51 | | #include "eac_dh.h" |
52 | | #include "eac_ecdh.h" |
53 | | #include "eac_err.h" |
54 | | #include "eac_util.h" |
55 | | #include "misc.h" |
56 | | #include "ssl_compat.h" |
57 | | #include <eac/eac.h> |
58 | | #include <openssl/bio.h> |
59 | | #include <openssl/crypto.h> |
60 | | #include <openssl/dh.h> |
61 | | #include <openssl/ec.h> |
62 | | #include <openssl/ecdsa.h> |
63 | | #include <openssl/evp.h> |
64 | | #include <openssl/rand.h> |
65 | | #include <openssl/rsa.h> |
66 | | |
67 | | /** |
68 | | * @brief Wrapper to the OpenSSL encryption functions. |
69 | | * |
70 | | * @param ctx (optional) |
71 | | * @param type |
72 | | * @param impl (optional) |
73 | | * @param key |
74 | | * @param iv (optional) |
75 | | * @param enc |
76 | | * @param in |
77 | | * |
78 | | * @return cipher of in or NULL if an error occurred |
79 | | */ |
80 | | static BUF_MEM * |
81 | | cipher(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, ENGINE *impl, |
82 | | const unsigned char *key, const unsigned char *iv, int enc, const BUF_MEM * in); |
83 | | static EVP_PKEY * |
84 | | EVP_PKEY_from_pubkey(EVP_PKEY *key, const BUF_MEM *pub, BN_CTX *bn_ctx); |
85 | | /** |
86 | | * @brief Computes the authentication token over the other parties public key |
87 | | * using the MAC key derived during PACE |
88 | | * |
89 | | */ |
90 | | static BUF_MEM * |
91 | | compute_authentication_token(int protocol, const KA_CTX *ka_ctx, EVP_PKEY *opp_key, |
92 | | BN_CTX *bn_ctx, enum eac_tr_version tr_version); |
93 | | /** |
94 | | * @brief Convert an ECDSA signature from plain format to X9.62 format |
95 | | * |
96 | | * @param[in] plain_sig signature in plain format |
97 | | * |
98 | | * @return signature in X9.62 format or NULL in case of an error */ |
99 | | static BUF_MEM * |
100 | | convert_from_plain_sig(const BUF_MEM *plain_sig); |
101 | | /** |
102 | | * @brief OpenSSL uses the X9.62 signature format, we have to convert it to the |
103 | | * plain format format specified in BSI TR 03111 |
104 | | * |
105 | | * @param x962_sig X9.62 formatted signature |
106 | | * |
107 | | * @return plain format signature or NULL in case of an error |
108 | | */ |
109 | | static BUF_MEM * |
110 | | convert_to_plain_sig(const BUF_MEM *x962_sig); |
111 | | |
112 | | BUF_MEM * |
113 | | hash(const EVP_MD * md, EVP_MD_CTX * ctx, ENGINE * impl, const BUF_MEM * in) |
114 | 0 | { |
115 | 0 | BUF_MEM * out = NULL; |
116 | 0 | EVP_MD_CTX * tmp_ctx = NULL; |
117 | 0 | unsigned int tmp_len; |
118 | |
|
119 | 0 | check((md && in), "Invalid arguments"); |
120 | |
|
121 | 0 | if (ctx) |
122 | 0 | tmp_ctx = ctx; |
123 | 0 | else { |
124 | 0 | tmp_ctx = EVP_MD_CTX_create(); |
125 | 0 | if (!tmp_ctx) |
126 | 0 | goto err; |
127 | 0 | } |
128 | | |
129 | 0 | tmp_len = EVP_MD_size(md); |
130 | 0 | out = BUF_MEM_create(tmp_len); |
131 | 0 | if (!out || !EVP_DigestInit_ex(tmp_ctx, md, impl) || |
132 | 0 | !EVP_DigestUpdate(tmp_ctx, in->data, in->length) || |
133 | 0 | !EVP_DigestFinal_ex(tmp_ctx, (unsigned char *) out->data, |
134 | 0 | &tmp_len)) |
135 | 0 | goto err; |
136 | 0 | out->length = tmp_len; |
137 | |
|
138 | 0 | if (!ctx) |
139 | 0 | EVP_MD_CTX_destroy(tmp_ctx); |
140 | |
|
141 | 0 | return out; |
142 | | |
143 | 0 | err: |
144 | 0 | if (out) |
145 | 0 | BUF_MEM_free(out); |
146 | 0 | if (tmp_ctx && !ctx) |
147 | 0 | EVP_MD_CTX_destroy(tmp_ctx); |
148 | |
|
149 | 0 | return NULL; |
150 | 0 | } |
151 | | |
152 | | static BUF_MEM * |
153 | | cipher(EVP_CIPHER_CTX *ctx, const EVP_CIPHER *type, ENGINE *impl, |
154 | | const unsigned char *key, const unsigned char *iv, int enc, const BUF_MEM * in) |
155 | 0 | { |
156 | 0 | BUF_MEM * out = NULL; |
157 | 0 | EVP_CIPHER_CTX * tmp_ctx = NULL; |
158 | 0 | int i; |
159 | 0 | unsigned long flags; |
160 | |
|
161 | 0 | check(in, "Invalid arguments"); |
162 | |
|
163 | 0 | if (ctx) |
164 | 0 | tmp_ctx = ctx; |
165 | 0 | else { |
166 | 0 | tmp_ctx = EVP_CIPHER_CTX_new(); |
167 | 0 | if (!tmp_ctx) |
168 | 0 | goto err; |
169 | 0 | EVP_CIPHER_CTX_init(tmp_ctx); |
170 | 0 | if (!EVP_CipherInit_ex(tmp_ctx, type, impl, key, iv, enc)) |
171 | 0 | goto err; |
172 | 0 | } |
173 | | |
174 | 0 | if (!EVP_CIPHER_CTX_cipher(tmp_ctx)) |
175 | 0 | goto err; |
176 | 0 | flags = EVP_CIPHER_flags(EVP_CIPHER_CTX_cipher(tmp_ctx)); |
177 | |
|
178 | 0 | if (flags & EVP_CIPH_NO_PADDING) { |
179 | 0 | i = in->length; |
180 | 0 | check((in->length % EVP_CIPHER_block_size(type) == 0), "Data is not of blocklength"); |
181 | 0 | } else |
182 | 0 | i = in->length + EVP_CIPHER_block_size(type); |
183 | | |
184 | 0 | out = BUF_MEM_create(i); |
185 | 0 | if (!out) |
186 | 0 | goto err; |
187 | | |
188 | 0 | if (!EVP_CipherUpdate(tmp_ctx, (unsigned char *) out->data, &i, |
189 | 0 | (unsigned char *) in->data, in->length)) |
190 | 0 | goto err; |
191 | 0 | out->length = i; |
192 | |
|
193 | 0 | if (!EVP_CipherFinal_ex(tmp_ctx, (unsigned char *) (out->data + out->length), |
194 | 0 | &i)) |
195 | 0 | goto err; |
196 | | |
197 | 0 | if (!(flags & EVP_CIPH_NO_PADDING)) |
198 | 0 | out->length += i; |
199 | |
|
200 | 0 | if (!ctx) |
201 | 0 | EVP_CIPHER_CTX_free(tmp_ctx); |
202 | |
|
203 | 0 | return out; |
204 | | |
205 | 0 | err: |
206 | |
|
207 | 0 | if (out) |
208 | 0 | BUF_MEM_free(out); |
209 | 0 | if (!ctx && tmp_ctx) |
210 | 0 | EVP_CIPHER_CTX_free(tmp_ctx); |
211 | |
|
212 | 0 | return NULL; |
213 | 0 | } |
214 | | |
215 | | BUF_MEM * |
216 | | cipher_no_pad(KA_CTX *ctx, EVP_CIPHER_CTX *cipher_ctx, const BUF_MEM *key_enc, const BUF_MEM *data, int enc) |
217 | 0 | { |
218 | 0 | BUF_MEM *out = NULL; |
219 | 0 | EVP_CIPHER_CTX *tmp_ctx = NULL; |
220 | |
|
221 | 0 | check(ctx, "Invalid arguments"); |
222 | |
|
223 | 0 | if (cipher_ctx) |
224 | 0 | tmp_ctx = cipher_ctx; |
225 | 0 | else { |
226 | 0 | tmp_ctx = EVP_CIPHER_CTX_new(); |
227 | 0 | if (!tmp_ctx) |
228 | 0 | goto err; |
229 | 0 | EVP_CIPHER_CTX_init(tmp_ctx); |
230 | 0 | } |
231 | | |
232 | 0 | if (!EVP_CipherInit_ex(tmp_ctx, ctx->cipher, ctx->cipher_engine, |
233 | 0 | (unsigned char *)key_enc->data, ctx->iv, enc) |
234 | 0 | || !EVP_CIPHER_CTX_set_padding(tmp_ctx, 0)) |
235 | 0 | goto err; |
236 | | |
237 | 0 | out = cipher(tmp_ctx, ctx->cipher, ctx->cipher_engine, |
238 | 0 | (unsigned char *)key_enc->data, ctx->iv, enc, data); |
239 | |
|
240 | 0 | err: |
241 | 0 | if (!cipher_ctx && tmp_ctx) |
242 | 0 | EVP_CIPHER_CTX_free(tmp_ctx); |
243 | |
|
244 | 0 | return out; |
245 | 0 | } |
246 | | |
247 | | BUF_MEM * |
248 | | cmac(CMAC_CTX *ctx, const EVP_CIPHER *type, const BUF_MEM * key, |
249 | | const BUF_MEM * in, size_t maclen) |
250 | 0 | { |
251 | 0 | CMAC_CTX * cmac_ctx = NULL; |
252 | 0 | BUF_MEM * out = NULL, * tmp = NULL; |
253 | 0 | size_t cmac_len = 0; |
254 | |
|
255 | 0 | check((key && in && type), "Invalid arguments"); |
256 | |
|
257 | 0 | check((key->length >= (size_t) EVP_CIPHER_key_length(type)), |
258 | 0 | "Key is too short"); |
259 | |
|
260 | 0 | if (ctx) |
261 | 0 | cmac_ctx = ctx; |
262 | 0 | else { |
263 | 0 | cmac_ctx = CMAC_CTX_new(); |
264 | 0 | } |
265 | | |
266 | | /* Initialize the CMAC context, feed in the data, and get the required |
267 | | * output buffer size */ |
268 | 0 | if (!cmac_ctx || |
269 | 0 | !CMAC_Init(cmac_ctx, key->data, EVP_CIPHER_key_length(type), |
270 | 0 | type, NULL) || |
271 | 0 | !CMAC_Update(cmac_ctx, in->data, in->length) || |
272 | 0 | !CMAC_Final(cmac_ctx, NULL, &cmac_len)) |
273 | 0 | goto err; |
274 | | |
275 | | /* get buffer in required size */ |
276 | 0 | out = BUF_MEM_create(cmac_len); |
277 | 0 | if (!out) |
278 | 0 | goto err; |
279 | | |
280 | | /* get the actual CMAC */ |
281 | 0 | if (!CMAC_Final(cmac_ctx, (unsigned char*) out->data, &out->length)) |
282 | 0 | goto err; |
283 | | |
284 | | /* Truncate the CMAC if necessary */ |
285 | 0 | if (cmac_len > maclen) { |
286 | 0 | tmp = BUF_MEM_create_init(out->data, maclen); |
287 | 0 | BUF_MEM_free(out); |
288 | 0 | out = tmp; |
289 | 0 | } |
290 | |
|
291 | 0 | if (!ctx) |
292 | 0 | CMAC_CTX_free(cmac_ctx); |
293 | |
|
294 | 0 | return out; |
295 | | |
296 | 0 | err: |
297 | 0 | if (cmac_ctx && !ctx) { |
298 | 0 | CMAC_CTX_free(cmac_ctx); |
299 | 0 | } |
300 | 0 | if (out) { |
301 | 0 | BUF_MEM_free(out); |
302 | 0 | } |
303 | |
|
304 | 0 | return NULL; |
305 | 0 | } |
306 | | |
307 | | BUF_MEM * |
308 | | randb(int numbytes) |
309 | 0 | { |
310 | 0 | BUF_MEM * r = BUF_MEM_new(); |
311 | 0 | if (!r || !BUF_MEM_grow(r, numbytes) || |
312 | 0 | !RAND_bytes((unsigned char *) r->data, numbytes)) |
313 | 0 | goto err; |
314 | | |
315 | 0 | return r; |
316 | | |
317 | 0 | err: |
318 | 0 | if (r) |
319 | 0 | BUF_MEM_free(r); |
320 | |
|
321 | 0 | return NULL; |
322 | 0 | } |
323 | | |
324 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
325 | | #include <openssl/provider.h> |
326 | | #endif |
327 | | |
328 | | BUF_MEM * |
329 | | retail_mac_des(const BUF_MEM * key, const BUF_MEM * in) |
330 | 0 | { |
331 | | /* ISO 9797-1 algorithm 3 retail mac without any padding */ |
332 | 0 | BUF_MEM * c_tmp = NULL, *d_tmp = NULL, *mac = NULL, *block = NULL; |
333 | 0 | EVP_CIPHER_CTX * ctx = NULL; |
334 | 0 | size_t len; |
335 | |
|
336 | 0 | check(key, "Invalid arguments"); |
337 | |
|
338 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
339 | | OSSL_PROVIDER *legacy = OSSL_PROVIDER_load(NULL, "legacy"); |
340 | | if (!legacy) |
341 | | goto err; |
342 | | #endif |
343 | |
|
344 | 0 | len = EVP_CIPHER_block_size(EVP_des_cbc()); |
345 | 0 | check(key->length >= 2*len, "Key too short"); |
346 | |
|
347 | 0 | ctx = EVP_CIPHER_CTX_new(); |
348 | 0 | if (!ctx) |
349 | 0 | goto err; |
350 | 0 | EVP_CIPHER_CTX_init(ctx); |
351 | 0 | if (!EVP_CipherInit_ex(ctx, EVP_des_cbc(), NULL, |
352 | 0 | (unsigned char *) key->data, NULL, 1) || |
353 | 0 | !EVP_CIPHER_CTX_set_padding(ctx, 0)) |
354 | 0 | goto err; |
355 | | |
356 | | /* get last block of des_cbc encrypted input */ |
357 | 0 | c_tmp = cipher(ctx, EVP_des_cbc(), NULL, NULL, NULL, 1, in); |
358 | 0 | if (!c_tmp) |
359 | 0 | goto err; |
360 | 0 | block = BUF_MEM_create_init(c_tmp->data + c_tmp->length - len, len); |
361 | | |
362 | | /* decrypt last block with the rest of the key */ |
363 | | /* IV is always NULL */ |
364 | 0 | if (!block || !EVP_CipherInit_ex(ctx, EVP_des_cbc(), NULL, |
365 | 0 | (unsigned char *) key->data + len, NULL, 0) || |
366 | 0 | !EVP_CIPHER_CTX_set_padding(ctx, 0)) |
367 | 0 | goto err; |
368 | 0 | d_tmp = cipher(ctx, EVP_des_cbc(), NULL, NULL, NULL, 0, block); |
369 | | |
370 | | /* encrypt last block with the first key */ |
371 | | /* IV is always NULL */ |
372 | 0 | if (!d_tmp || !EVP_CipherInit_ex(ctx, EVP_des_cbc(), NULL, |
373 | 0 | (unsigned char *) key->data, NULL, 1) || |
374 | 0 | !EVP_CIPHER_CTX_set_padding(ctx, 0)) |
375 | 0 | goto err; |
376 | 0 | mac = cipher(ctx, EVP_des_cbc(), NULL, NULL, NULL, 1, d_tmp); |
377 | |
|
378 | 0 | BUF_MEM_free(block); |
379 | 0 | BUF_MEM_free(c_tmp); |
380 | 0 | BUF_MEM_free(d_tmp); |
381 | 0 | EVP_CIPHER_CTX_free(ctx); |
382 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
383 | | OSSL_PROVIDER_unload(legacy); |
384 | | #endif |
385 | |
|
386 | 0 | return mac; |
387 | | |
388 | 0 | err: |
389 | 0 | if (block) |
390 | 0 | BUF_MEM_free(block); |
391 | 0 | if (c_tmp) |
392 | 0 | BUF_MEM_free(c_tmp); |
393 | 0 | if (d_tmp) |
394 | 0 | BUF_MEM_free(d_tmp); |
395 | 0 | if (ctx) |
396 | 0 | EVP_CIPHER_CTX_free(ctx); |
397 | | #if OPENSSL_VERSION_NUMBER >= 0x30000000L |
398 | | if (legacy) |
399 | | OSSL_PROVIDER_unload(legacy); |
400 | | #endif |
401 | |
|
402 | 0 | return NULL; |
403 | 0 | } |
404 | | |
405 | | BUF_MEM * |
406 | | add_iso_pad(const BUF_MEM * m, int block_size) |
407 | 0 | { |
408 | 0 | BUF_MEM * out = NULL; |
409 | 0 | int p_len; |
410 | |
|
411 | 0 | check(m, "Invalid arguments"); |
412 | | |
413 | | /* calculate length of padded message */ |
414 | 0 | p_len = (m->length / block_size) * block_size + block_size; |
415 | |
|
416 | 0 | out = BUF_MEM_create(p_len); |
417 | 0 | if (!out) |
418 | 0 | goto err; |
419 | | |
420 | 0 | memcpy(out->data, m->data, m->length); |
421 | | |
422 | | /* now add iso padding */ |
423 | 0 | memset(out->data + m->length, 0x80, 1); |
424 | 0 | memset(out->data + m->length + 1, 0, p_len - m->length - 1); |
425 | |
|
426 | 0 | err: |
427 | 0 | return out; |
428 | 0 | } |
429 | | |
430 | | int encode_ssc(const BIGNUM *ssc, const KA_CTX *ctx, unsigned char **encoded) |
431 | 0 | { |
432 | 0 | unsigned char *p; |
433 | 0 | size_t en_len, bn_len; |
434 | |
|
435 | 0 | if (!ctx || !encoded) { |
436 | 0 | log_err("Invalid arguments"); |
437 | 0 | return -1; |
438 | 0 | } |
439 | | |
440 | 0 | en_len = EVP_CIPHER_block_size(ctx->cipher); |
441 | 0 | p = OPENSSL_realloc(*encoded, en_len); |
442 | 0 | if (!p) { |
443 | 0 | log_err("Realloc failure"); |
444 | 0 | return -1; |
445 | 0 | } |
446 | 0 | *encoded = p; |
447 | |
|
448 | 0 | bn_len = BN_num_bytes(ssc); |
449 | |
|
450 | 0 | if (bn_len <= en_len) { |
451 | 0 | memset(*encoded, 0, en_len - bn_len); |
452 | 0 | BN_bn2bin(ssc, *encoded + en_len - bn_len); |
453 | 0 | } else { |
454 | 0 | p = OPENSSL_malloc(bn_len); |
455 | 0 | if (!p) |
456 | 0 | return -1; |
457 | 0 | BN_bn2bin(ssc, p); |
458 | 0 | memcpy(*encoded, p + bn_len - en_len, en_len); |
459 | 0 | OPENSSL_free(p); |
460 | 0 | } |
461 | | |
462 | 0 | return en_len; |
463 | 0 | } |
464 | | |
465 | | int update_iv(KA_CTX *ctx, EVP_CIPHER_CTX *cipher_ctx, const BIGNUM *ssc) |
466 | 0 | { |
467 | 0 | BUF_MEM *sscbuf = NULL, *ivbuf = NULL; |
468 | 0 | const EVP_CIPHER *ivcipher = NULL, *oldcipher; |
469 | 0 | unsigned char *ssc_buf = NULL; |
470 | 0 | unsigned char *p; |
471 | 0 | int r = 0; |
472 | |
|
473 | 0 | check(ctx, "Invalid arguments"); |
474 | |
|
475 | 0 | switch (EVP_CIPHER_nid(ctx->cipher)) { |
476 | 0 | case NID_aes_128_cbc: |
477 | 0 | if (!ivcipher) |
478 | 0 | ivcipher = EVP_aes_128_ecb(); |
479 | | /* fall through */ |
480 | 0 | case NID_aes_192_cbc: |
481 | 0 | if (!ivcipher) |
482 | 0 | ivcipher = EVP_aes_192_ecb(); |
483 | | /* fall through */ |
484 | 0 | case NID_aes_256_cbc: |
485 | 0 | if (!ivcipher) |
486 | 0 | ivcipher = EVP_aes_256_ecb(); |
487 | | |
488 | | /* For AES decryption the IV is not needed, |
489 | | * so we always set it to the encryption IV=E(K_Enc, SSC) */ |
490 | 0 | r = encode_ssc(ssc, ctx, &ssc_buf); |
491 | 0 | if (r < 0) |
492 | 0 | goto err; |
493 | 0 | sscbuf = BUF_MEM_create_init(ssc_buf, r); |
494 | 0 | if (!sscbuf) |
495 | 0 | goto err; |
496 | 0 | oldcipher = ctx->cipher; |
497 | 0 | ctx->cipher = ivcipher; |
498 | 0 | ivbuf = cipher_no_pad(ctx, cipher_ctx, ctx->k_enc, sscbuf, 1); |
499 | 0 | ctx->cipher = oldcipher; |
500 | 0 | if (!ivbuf) |
501 | 0 | goto err; |
502 | 0 | if (0 != ivbuf->length) { |
503 | 0 | p = OPENSSL_realloc(ctx->iv, ivbuf->length); |
504 | 0 | if (!p) |
505 | 0 | goto err; |
506 | 0 | ctx->iv = p; |
507 | 0 | memcpy(ctx->iv, ivbuf->data, ivbuf->length); |
508 | 0 | } |
509 | 0 | break; |
510 | | |
511 | 0 | case NID_des_ede_cbc: |
512 | | /* For 3DES encryption or decryption the IV is always NULL */ |
513 | 0 | if (ctx->iv) |
514 | 0 | OPENSSL_free(ctx->iv); |
515 | 0 | ctx->iv = NULL; |
516 | 0 | break; |
517 | | |
518 | 0 | default: |
519 | 0 | log_err("Unknown cipher"); |
520 | 0 | goto err; |
521 | 0 | } |
522 | | |
523 | 0 | r = 1; |
524 | |
|
525 | 0 | err: |
526 | 0 | if (ssc_buf) |
527 | 0 | OPENSSL_free(ssc_buf); |
528 | 0 | if (sscbuf) |
529 | 0 | BUF_MEM_free(sscbuf); |
530 | 0 | if (ivbuf) |
531 | 0 | BUF_MEM_free(ivbuf); |
532 | |
|
533 | 0 | return r; |
534 | 0 | } |
535 | | |
536 | | int |
537 | | is_char_str(const unsigned char *str, const size_t length) |
538 | 0 | { |
539 | 0 | const unsigned char *s = NULL; |
540 | 0 | size_t i = 0; |
541 | |
|
542 | 0 | if (!str && length) |
543 | 0 | return 0; |
544 | | |
545 | 0 | s = str; |
546 | 0 | i = length; |
547 | |
|
548 | 0 | while (i) { |
549 | 0 | if (*s <= 0x1f || (0x7f <= *s && *s <= 0x9f)) { |
550 | 0 | log_err("Invalid data"); |
551 | 0 | return 0; |
552 | 0 | } |
553 | 0 | s++; |
554 | 0 | i--; |
555 | 0 | } |
556 | | |
557 | 0 | return 1; |
558 | 0 | } |
559 | | |
560 | | int |
561 | | is_bcd(const unsigned char *data, size_t length) |
562 | 0 | { |
563 | 0 | size_t i; |
564 | |
|
565 | 0 | if (!data && length) |
566 | 0 | return 0; |
567 | | |
568 | 0 | for(i = 0; i < length; i++) { |
569 | 0 | if (data[i] > 0x9) { |
570 | 0 | log_err("Invalid data"); |
571 | 0 | return 0; |
572 | 0 | } |
573 | 0 | } |
574 | 0 | return 1; |
575 | 0 | } |
576 | | |
577 | | int |
578 | | is_chr(const unsigned char *data, size_t length) |
579 | 0 | { |
580 | 0 | size_t i; |
581 | | |
582 | | /* check for length of country code, holder mnemonic and sequence number */ |
583 | 0 | if (!data || length < 2+5 || 2+9+5 < length) |
584 | 0 | return 0; |
585 | | |
586 | | /* country code must be an upper ASCII character */ |
587 | 0 | if (!(('A' <= data[0] && data[0] <= 'Z') && ('A' <= data[1] && data[1] <= 'Z'))) |
588 | 0 | return 0; |
589 | | |
590 | | /* holder mnemonic must in ISO/IEC 8859Â1 Character Set */ |
591 | 0 | if (!is_char_str(data+2, length-2-5)) |
592 | 0 | return 0; |
593 | | |
594 | | /* sequence number must contain 0..9 and A..Z */ |
595 | 0 | for (i = length-5; i < length; i++) { |
596 | 0 | if (!(('A' <= data[i] && data[i] <= 'Z') |
597 | 0 | || ('0' <= data[i] && data[i] <= '9'))) |
598 | 0 | return 0; |
599 | 0 | } |
600 | | |
601 | 0 | return 1; |
602 | 0 | } |
603 | | |
604 | | BUF_MEM * |
605 | | authenticate(const KA_CTX *ctx, const BUF_MEM *data) |
606 | 0 | { |
607 | 0 | switch (EVP_CIPHER_nid(ctx->cipher)) { |
608 | 0 | case NID_des_ede_cbc: |
609 | 0 | return retail_mac_des(ctx->k_mac, data); |
610 | 0 | case NID_aes_128_cbc: |
611 | 0 | case NID_aes_192_cbc: |
612 | 0 | case NID_aes_256_cbc: |
613 | 0 | return cmac(ctx->cmac_ctx, ctx->cipher, ctx->k_mac, data, |
614 | 0 | EAC_AES_MAC_LENGTH); |
615 | 0 | default: |
616 | 0 | log_err("Unknown cipher"); |
617 | 0 | return NULL; |
618 | 0 | } |
619 | 0 | } |
620 | | |
621 | | static EVP_PKEY * |
622 | | EVP_PKEY_from_pubkey(EVP_PKEY *key, const BUF_MEM *pub, BN_CTX *bn_ctx) |
623 | 0 | { |
624 | 0 | EVP_PKEY *out = NULL; |
625 | |
|
626 | 0 | check(pub, "Invalid arguments"); |
627 | |
|
628 | 0 | out = EVP_PKEY_dup(key); |
629 | 0 | check(out, ""); |
630 | |
|
631 | 0 | if (!EVP_PKEY_set_keys(out, NULL, 0, |
632 | 0 | (const unsigned char *) pub->data, pub->length, bn_ctx)) { |
633 | 0 | EVP_PKEY_free(out); |
634 | 0 | out = NULL; |
635 | 0 | goto err; |
636 | 0 | } |
637 | | |
638 | 0 | err: |
639 | 0 | return out; |
640 | 0 | } |
641 | | |
642 | | BUF_MEM * |
643 | | get_authentication_token(int protocol, const KA_CTX *ka_ctx, BN_CTX *bn_ctx, |
644 | | enum eac_tr_version tr_version, const BUF_MEM *pub_opp) |
645 | 0 | { |
646 | 0 | BUF_MEM *out = NULL; |
647 | 0 | EVP_PKEY *opp_key = NULL; |
648 | |
|
649 | 0 | check(ka_ctx, "Invalid arguments"); |
650 | |
|
651 | 0 | opp_key = EVP_PKEY_from_pubkey(ka_ctx->key, pub_opp, |
652 | 0 | bn_ctx); |
653 | 0 | if (!opp_key) |
654 | 0 | goto err; |
655 | | |
656 | | |
657 | 0 | out = compute_authentication_token(protocol, ka_ctx, opp_key, |
658 | 0 | bn_ctx, tr_version); |
659 | |
|
660 | 0 | err: |
661 | 0 | EVP_PKEY_free(opp_key); |
662 | |
|
663 | 0 | return out; |
664 | 0 | } |
665 | | |
666 | | BUF_MEM * |
667 | | compute_authentication_token(int protocol, const KA_CTX *ka_ctx, EVP_PKEY *opp_key, |
668 | | BN_CTX *bn_ctx, enum eac_tr_version tr_version) |
669 | 0 | { |
670 | 0 | BUF_MEM *asn1 = NULL, *out = NULL, *pad =NULL; |
671 | |
|
672 | 0 | check(ka_ctx, "Invalid arguments"); |
673 | |
|
674 | 0 | asn1 = asn1_pubkey(protocol, opp_key, bn_ctx, tr_version); |
675 | | |
676 | | /* ISO 9797-1 algorithm 3 retail MAC now needs extra padding (padding method 2) */ |
677 | 0 | if (EVP_CIPHER_nid(ka_ctx->cipher) == NID_des_ede_cbc) { |
678 | 0 | pad = add_iso_pad(asn1, EVP_CIPHER_block_size(ka_ctx->cipher)); |
679 | 0 | if (!pad) |
680 | 0 | goto err; |
681 | 0 | out = authenticate(ka_ctx, pad); |
682 | 0 | } else { |
683 | 0 | out = authenticate(ka_ctx, asn1); |
684 | 0 | } |
685 | | |
686 | 0 | err: |
687 | 0 | if (asn1) |
688 | 0 | BUF_MEM_free(asn1); |
689 | 0 | if (pad) |
690 | 0 | BUF_MEM_free(pad); |
691 | |
|
692 | 0 | return out; |
693 | 0 | } |
694 | | |
695 | | int |
696 | | verify_authentication_token(int protocol, const KA_CTX *ka_ctx, BN_CTX *bn_ctx, |
697 | | enum eac_tr_version tr_version, const BUF_MEM *token) |
698 | 0 | { |
699 | 0 | int rv; |
700 | 0 | BUF_MEM *token_verify = NULL; |
701 | |
|
702 | 0 | if (!ka_ctx || !token) { |
703 | 0 | log_err("Invalid arguments"); |
704 | 0 | return -1; |
705 | 0 | } |
706 | | |
707 | 0 | token_verify = compute_authentication_token(protocol, ka_ctx, ka_ctx->key, |
708 | 0 | bn_ctx, tr_version); |
709 | 0 | if (!token_verify) |
710 | 0 | return -1; |
711 | | |
712 | 0 | if (token_verify->length != token->length || |
713 | 0 | CRYPTO_memcmp(token_verify->data, token->data, token_verify->length)) |
714 | 0 | rv = 0; |
715 | 0 | else |
716 | 0 | rv = 1; |
717 | |
|
718 | 0 | BUF_MEM_free(token_verify); |
719 | |
|
720 | 0 | return rv; |
721 | 0 | } |
722 | | |
723 | | BUF_MEM * |
724 | | Comp(EVP_PKEY *key, const BUF_MEM *pub, BN_CTX *bn_ctx, EVP_MD_CTX *md_ctx) |
725 | 0 | { |
726 | 0 | BUF_MEM *out = NULL; |
727 | 0 | const EC_GROUP *group; |
728 | 0 | EC_POINT *ecp = NULL; |
729 | 0 | EC_KEY *ec = NULL; |
730 | 0 | BIGNUM *x = NULL, *y = NULL; |
731 | |
|
732 | 0 | check((key && pub), "Invalid arguments"); |
733 | |
|
734 | 0 | BN_CTX_start(bn_ctx); |
735 | 0 | switch (EVP_PKEY_base_id(key)) { |
736 | 0 | case EVP_PKEY_DH: |
737 | 0 | case EVP_PKEY_DHX: |
738 | 0 | out = hash(EVP_sha1(), md_ctx, NULL, pub); |
739 | 0 | break; |
740 | | |
741 | 0 | case EVP_PKEY_EC: |
742 | 0 | ec = EVP_PKEY_get1_EC_KEY(key); |
743 | 0 | if (!ec) |
744 | 0 | goto err; |
745 | | |
746 | 0 | group = EC_KEY_get0_group(ec); |
747 | 0 | ecp = EC_POINT_new(group); |
748 | 0 | x = BN_CTX_get(bn_ctx); |
749 | 0 | y = BN_CTX_get(bn_ctx); |
750 | |
|
751 | 0 | if(!ecp || !x || !y |
752 | 0 | || !EC_POINT_oct2point(group, ecp, |
753 | 0 | (unsigned char *) pub->data, pub->length, bn_ctx) |
754 | 0 | || !EC_POINT_get_affine_coordinates(group, ecp, x, y, bn_ctx)) |
755 | 0 | goto err; |
756 | | |
757 | 0 | out = BUF_MEM_create(BN_num_bytes(x)); |
758 | 0 | if(!out || !BN_bn2bin(x, (unsigned char *) out->data)) |
759 | 0 | goto err; |
760 | 0 | break; |
761 | | |
762 | 0 | default: |
763 | 0 | log_err("Unknown protocol"); |
764 | 0 | goto err; |
765 | 0 | } |
766 | | |
767 | 0 | err: |
768 | 0 | if (ecp) |
769 | 0 | EC_POINT_free(ecp); |
770 | | /* Decrease the reference count, the key is still available in the EVP_PKEY |
771 | | * structure */ |
772 | 0 | if (ec) |
773 | 0 | EC_KEY_free(ec); |
774 | 0 | BN_CTX_end(bn_ctx); |
775 | |
|
776 | 0 | return out; |
777 | 0 | } |
778 | | |
779 | 0 | int EVP_PKEY_set_std_dp(EVP_PKEY *key, int stnd_dp) { |
780 | |
|
781 | 0 | DH *dh = NULL; |
782 | 0 | EC_KEY *ec = NULL; |
783 | |
|
784 | 0 | if (!key) { |
785 | 0 | log_err("Invalid arguments"); |
786 | 0 | return 0; |
787 | 0 | } |
788 | | |
789 | | /* Generate key from standardized domain parameters */ |
790 | 0 | switch(stnd_dp) { |
791 | 0 | case 0: |
792 | 0 | case 1: |
793 | 0 | case 2: |
794 | 0 | if (!init_dh(&dh, stnd_dp)) |
795 | 0 | return 0; |
796 | 0 | EVP_PKEY_set1_DH(key, dh); |
797 | | /* Decrement reference count */ |
798 | 0 | DH_free(dh); |
799 | 0 | break; |
800 | | |
801 | 0 | case 8: |
802 | 0 | case 9: |
803 | 0 | case 10: |
804 | 0 | case 11: |
805 | 0 | case 12: |
806 | 0 | case 13: |
807 | 0 | case 14: |
808 | 0 | case 15: |
809 | 0 | case 16: |
810 | 0 | case 17: |
811 | 0 | case 18: |
812 | 0 | if (!init_ecdh(&ec, stnd_dp)) |
813 | 0 | return 0; |
814 | 0 | EVP_PKEY_set1_EC_KEY(key, ec); |
815 | | /* Decrement reference count */ |
816 | 0 | EC_KEY_free(ec); |
817 | 0 | break; |
818 | | |
819 | 0 | default: |
820 | 0 | log_err("Invalid arguments"); |
821 | 0 | return 0; |
822 | 0 | } |
823 | | |
824 | 0 | return 1; |
825 | 0 | } |
826 | | |
827 | | void |
828 | | BUF_MEM_clear_free(BUF_MEM *b) |
829 | 0 | { |
830 | 0 | if (b) { |
831 | 0 | OPENSSL_cleanse(b->data, b->max); |
832 | 0 | BUF_MEM_free(b); |
833 | 0 | } |
834 | 0 | } |
835 | | |
836 | | int |
837 | | EVP_PKEY_set_keys(EVP_PKEY *evp_pkey, |
838 | | const unsigned char *privkey, size_t privkey_len, |
839 | | const unsigned char *pubkey, size_t pubkey_len, |
840 | | BN_CTX *bn_ctx) |
841 | 0 | { |
842 | 0 | EC_KEY *ec_key = NULL; |
843 | 0 | DH *dh = NULL; |
844 | 0 | EC_POINT *ec_point = NULL; |
845 | 0 | BIGNUM *bn = NULL, *dh_pub_key, *dh_priv_key; |
846 | 0 | int ok = 0; |
847 | 0 | const EC_GROUP *group; |
848 | |
|
849 | 0 | check(evp_pkey, "Invalid arguments"); |
850 | |
|
851 | 0 | switch (EVP_PKEY_base_id(evp_pkey)) { |
852 | 0 | case EVP_PKEY_EC: |
853 | 0 | ec_key = EVP_PKEY_get1_EC_KEY(evp_pkey); |
854 | 0 | if (!ec_key) |
855 | 0 | goto err; |
856 | 0 | group = EC_KEY_get0_group(ec_key); |
857 | |
|
858 | 0 | if (pubkey) { |
859 | 0 | ec_point = EC_POINT_new(group); |
860 | 0 | if (!ec_point |
861 | 0 | || !EC_POINT_oct2point(group, ec_point, pubkey, |
862 | 0 | pubkey_len, bn_ctx) |
863 | 0 | || !EC_KEY_set_public_key(ec_key, ec_point)) |
864 | 0 | goto err; |
865 | 0 | } |
866 | 0 | if (privkey) { |
867 | 0 | bn = BN_bin2bn(privkey, privkey_len, bn); |
868 | 0 | if (!bn || !EC_KEY_set_private_key(ec_key, bn)) |
869 | 0 | goto err; |
870 | 0 | } |
871 | | |
872 | 0 | if (!EVP_PKEY_set1_EC_KEY(evp_pkey, ec_key)) |
873 | 0 | goto err; |
874 | 0 | break; |
875 | | |
876 | 0 | case EVP_PKEY_DH: |
877 | 0 | case EVP_PKEY_DHX: |
878 | 0 | dh = EVP_PKEY_get1_DH(evp_pkey); |
879 | 0 | if (!dh) |
880 | 0 | goto err; |
881 | | |
882 | 0 | if (pubkey) { |
883 | 0 | dh_pub_key = BN_bin2bn(pubkey, pubkey_len, NULL); |
884 | 0 | if (!dh_pub_key || !DH_set0_key(dh, dh_pub_key, NULL)) |
885 | 0 | goto err; |
886 | 0 | } |
887 | 0 | if (privkey) { |
888 | 0 | dh_priv_key = BN_bin2bn(privkey, privkey_len, NULL); |
889 | 0 | if (!dh_priv_key || !DH_set0_key(dh, NULL, dh_priv_key)) |
890 | 0 | goto err; |
891 | 0 | } |
892 | | |
893 | 0 | if (!EVP_PKEY_set1_DH(evp_pkey, dh)) |
894 | 0 | goto err; |
895 | 0 | break; |
896 | | |
897 | 0 | default: |
898 | 0 | log_err("Unknown type of key %d", EVP_PKEY_base_id(evp_pkey)); |
899 | 0 | goto err; |
900 | 0 | break; |
901 | 0 | } |
902 | | |
903 | 0 | ok = 1; |
904 | |
|
905 | 0 | err: |
906 | 0 | if (bn) |
907 | 0 | BN_clear_free(bn); |
908 | 0 | if (ec_key) |
909 | 0 | EC_KEY_free(ec_key); |
910 | 0 | if (dh) |
911 | 0 | DH_free(dh); |
912 | 0 | if (ec_point) |
913 | 0 | EC_POINT_clear_free(ec_point); |
914 | |
|
915 | 0 | return ok; |
916 | 0 | } |
917 | | |
918 | | BUF_MEM * |
919 | | get_pubkey(EVP_PKEY *key, BN_CTX *bn_ctx) |
920 | 0 | { |
921 | 0 | BUF_MEM *out; |
922 | 0 | DH *dh; |
923 | 0 | EC_KEY *ec; |
924 | 0 | const EC_POINT *ec_pub; |
925 | 0 | const BIGNUM *dh_pub_key; |
926 | |
|
927 | 0 | check_return(key, "invalid arguments"); |
928 | |
|
929 | 0 | switch (EVP_PKEY_base_id(key)) { |
930 | 0 | case EVP_PKEY_DH: |
931 | 0 | case EVP_PKEY_DHX: |
932 | 0 | dh = EVP_PKEY_get1_DH(key); |
933 | 0 | check_return(dh, "no DH key"); |
934 | |
|
935 | 0 | DH_get0_key(dh, &dh_pub_key, NULL); |
936 | 0 | out = BN_bn2buf(dh_pub_key); |
937 | |
|
938 | 0 | DH_free(dh); |
939 | 0 | break; |
940 | | |
941 | 0 | case EVP_PKEY_EC: |
942 | 0 | ec = EVP_PKEY_get1_EC_KEY(key); |
943 | 0 | check_return(ec, "no EC key"); |
944 | |
|
945 | 0 | ec_pub = EC_KEY_get0_public_key(ec); |
946 | 0 | check_return(ec_pub, "no EC public key"); |
947 | |
|
948 | 0 | out = EC_POINT_point2mem(ec, bn_ctx, ec_pub); |
949 | |
|
950 | 0 | EC_KEY_free(ec); |
951 | 0 | break; |
952 | | |
953 | 0 | default: |
954 | 0 | log_err("unknown type of key"); |
955 | 0 | return NULL; |
956 | 0 | } |
957 | | |
958 | 0 | return out; |
959 | 0 | } |
960 | | |
961 | | BUF_MEM * |
962 | | convert_from_plain_sig(const BUF_MEM *plain_sig) |
963 | 0 | { |
964 | 0 | ECDSA_SIG *ecdsa_sig = NULL; |
965 | 0 | BIGNUM *r = NULL, *s = NULL; |
966 | 0 | BUF_MEM *x962_sig = NULL; |
967 | 0 | int l; |
968 | 0 | unsigned char *p = NULL; |
969 | |
|
970 | 0 | check(plain_sig, "Invalid arguments"); |
971 | |
|
972 | 0 | check(plain_sig->length%2 == 0, "Invalid data"); |
973 | |
|
974 | 0 | ecdsa_sig = ECDSA_SIG_new(); |
975 | 0 | if (!ecdsa_sig) |
976 | 0 | goto err; |
977 | | |
978 | | /* The first l/2 bytes of the plain signature contain the number r, the second |
979 | | * l/2 bytes contain the number s. */ |
980 | 0 | r = BN_bin2bn((unsigned char *) plain_sig->data, |
981 | 0 | plain_sig->length/2, NULL); |
982 | 0 | s = BN_bin2bn((unsigned char *) plain_sig->data + plain_sig->length/2, |
983 | 0 | plain_sig->length/2, NULL); |
984 | 0 | if (!r || !s || !ECDSA_SIG_set0(ecdsa_sig, r, s)) |
985 | 0 | goto err; |
986 | 0 | r = NULL; |
987 | 0 | s = NULL; |
988 | | |
989 | | /* ASN.1 encode the signature*/ |
990 | 0 | l = i2d_ECDSA_SIG(ecdsa_sig, &p); |
991 | 0 | if (l < 0) |
992 | 0 | goto err; |
993 | 0 | x962_sig = BUF_MEM_create_init(p, l); |
994 | |
|
995 | 0 | err: |
996 | 0 | if (p) |
997 | 0 | OPENSSL_free(p); |
998 | 0 | if (ecdsa_sig) |
999 | 0 | ECDSA_SIG_free(ecdsa_sig); |
1000 | 0 | if (r) |
1001 | 0 | BN_free(r); |
1002 | 0 | if (s) |
1003 | 0 | BN_free(s); |
1004 | |
|
1005 | 0 | return x962_sig; |
1006 | 0 | } |
1007 | | |
1008 | | BUF_MEM * |
1009 | | convert_to_plain_sig(const BUF_MEM *x962_sig) |
1010 | 0 | { |
1011 | 0 | size_t r_len, s_len, rs_max; |
1012 | 0 | BUF_MEM *plain_sig_buf = NULL; |
1013 | 0 | ECDSA_SIG *tmp_sig = NULL; |
1014 | 0 | const unsigned char *tmp; |
1015 | 0 | unsigned char *r = NULL, *s = NULL; |
1016 | 0 | const BIGNUM *bn_r, *bn_s; |
1017 | |
|
1018 | 0 | check_return(x962_sig, "Invalid arguments"); |
1019 | | |
1020 | | /* Convert the ASN.1 data to a C structure*/ |
1021 | 0 | tmp = (unsigned char*) x962_sig->data; |
1022 | 0 | tmp_sig = ECDSA_SIG_new(); |
1023 | 0 | if (!tmp_sig) |
1024 | 0 | goto err; |
1025 | 0 | if (!d2i_ECDSA_SIG(&tmp_sig, &tmp, x962_sig->length)) |
1026 | 0 | goto err; |
1027 | | |
1028 | 0 | ECDSA_SIG_get0(tmp_sig, &bn_r, &bn_s); |
1029 | | |
1030 | | /* Extract the parameters r and s*/ |
1031 | 0 | r_len = BN_num_bytes(bn_r); |
1032 | 0 | s_len = BN_num_bytes(bn_s); |
1033 | 0 | rs_max = r_len > s_len ? r_len : s_len; |
1034 | 0 | r = OPENSSL_malloc(rs_max); |
1035 | 0 | s = OPENSSL_malloc(rs_max); |
1036 | 0 | if (!r || !s) |
1037 | 0 | goto err; |
1038 | | |
1039 | | /* Convert r and s to a binary representation */ |
1040 | 0 | if (!BN_bn2bin(bn_r, r + rs_max - r_len)) |
1041 | 0 | goto err; |
1042 | 0 | if (!BN_bn2bin(bn_s, s + rs_max - s_len)) |
1043 | 0 | goto err; |
1044 | | /* r and s must be padded with leading zero bytes to ensure they have the |
1045 | | * same length */ |
1046 | 0 | memset(r, 0, rs_max - r_len); |
1047 | 0 | memset(s, 0, rs_max - s_len); |
1048 | | |
1049 | | /* concatenate r and s to get the plain signature format */ |
1050 | 0 | plain_sig_buf = BUF_MEM_create(rs_max + rs_max); |
1051 | 0 | if (!plain_sig_buf) |
1052 | 0 | goto err; |
1053 | 0 | memcpy(plain_sig_buf->data, r, rs_max); |
1054 | 0 | memcpy(plain_sig_buf->data + rs_max, s, rs_max); |
1055 | |
|
1056 | 0 | OPENSSL_free(r); |
1057 | 0 | OPENSSL_free(s); |
1058 | 0 | ECDSA_SIG_free(tmp_sig); |
1059 | |
|
1060 | 0 | return plain_sig_buf; |
1061 | | |
1062 | 0 | err: |
1063 | 0 | if (r) |
1064 | 0 | OPENSSL_free(r); |
1065 | 0 | if (s) |
1066 | 0 | OPENSSL_free(s); |
1067 | 0 | if (tmp_sig) |
1068 | 0 | ECDSA_SIG_free(tmp_sig); |
1069 | 0 | return NULL; |
1070 | 0 | } |
1071 | | |
1072 | | const EVP_MD * |
1073 | | eac_oid2md(int protocol) |
1074 | 0 | { |
1075 | 0 | if ( protocol == NID_id_TA_ECDSA_SHA_1 |
1076 | 0 | || protocol == NID_id_TA_RSA_v1_5_SHA_1 |
1077 | 0 | || protocol == NID_id_TA_RSA_PSS_SHA_1) { |
1078 | 0 | return EVP_sha1(); |
1079 | 0 | } else if (protocol == NID_id_TA_ECDSA_SHA_224) { |
1080 | 0 | return EVP_sha224(); |
1081 | 0 | } else if (protocol == NID_id_TA_ECDSA_SHA_256 |
1082 | 0 | || protocol == NID_id_TA_RSA_v1_5_SHA_256 |
1083 | 0 | || protocol == NID_id_TA_RSA_PSS_SHA_256) { |
1084 | 0 | return EVP_sha256(); |
1085 | 0 | } else if (protocol == NID_id_TA_ECDSA_SHA_384) { |
1086 | 0 | return EVP_sha384(); |
1087 | 0 | } else if (protocol == NID_id_TA_ECDSA_SHA_512 |
1088 | 0 | || protocol == NID_id_TA_RSA_v1_5_SHA_512 |
1089 | 0 | || protocol == NID_id_TA_RSA_PSS_SHA_512) { |
1090 | 0 | return EVP_sha512(); |
1091 | 0 | } else { |
1092 | 0 | log_err("Unknown protocol"); |
1093 | 0 | return NULL; |
1094 | 0 | } |
1095 | 0 | } |
1096 | | |
1097 | | int |
1098 | | EAC_verify(int protocol, EVP_PKEY *key, const BUF_MEM *signature, |
1099 | | const BUF_MEM *data) |
1100 | 0 | { |
1101 | 0 | BUF_MEM *verification_data = NULL, *signature_to_verify = NULL; |
1102 | 0 | EVP_PKEY_CTX *tmp_key_ctx = NULL; |
1103 | 0 | int ret = -1; |
1104 | 0 | const EVP_MD *md = eac_oid2md(protocol); |
1105 | 0 | int type; |
1106 | |
|
1107 | 0 | check((key && signature), "Invalid arguments"); |
1108 | |
|
1109 | 0 | tmp_key_ctx = EVP_PKEY_CTX_new(key, NULL); |
1110 | 0 | if (!tmp_key_ctx || !md |
1111 | 0 | || EVP_PKEY_verify_init(tmp_key_ctx) <= 0 |
1112 | 0 | || EVP_PKEY_CTX_set_signature_md(tmp_key_ctx, md) <= 0) |
1113 | 0 | goto err; |
1114 | | |
1115 | | |
1116 | 0 | type = EVP_PKEY_base_id(key); |
1117 | 0 | if ( protocol == NID_id_TA_ECDSA_SHA_1 |
1118 | 0 | || protocol == NID_id_TA_ECDSA_SHA_224 |
1119 | 0 | || protocol == NID_id_TA_ECDSA_SHA_256 |
1120 | 0 | || protocol == NID_id_TA_ECDSA_SHA_384 |
1121 | 0 | || protocol == NID_id_TA_ECDSA_SHA_512) { |
1122 | 0 | if (!(type == EVP_PKEY_EC)) |
1123 | 0 | goto err; |
1124 | | |
1125 | | /* EAC signatures are always in plain signature format for EC curves but |
1126 | | * OpenSSL only creates X.509 format. Therefore we need to convert between |
1127 | | * these formats. */ |
1128 | 0 | signature_to_verify = convert_from_plain_sig(signature); |
1129 | 0 | if (!signature_to_verify) |
1130 | 0 | goto err; |
1131 | |
|
1132 | 0 | } else if (protocol == NID_id_TA_RSA_v1_5_SHA_1 |
1133 | 0 | || protocol == NID_id_TA_RSA_v1_5_SHA_256 |
1134 | 0 | || protocol == NID_id_TA_RSA_v1_5_SHA_512) { |
1135 | 0 | if (!(type == EVP_PKEY_RSA)) |
1136 | 0 | goto err; |
1137 | | |
1138 | 0 | signature_to_verify = BUF_MEM_create_init(signature->data, |
1139 | 0 | signature->length); |
1140 | 0 | if (!EVP_PKEY_CTX_set_rsa_padding(tmp_key_ctx, RSA_PKCS1_PADDING) |
1141 | 0 | || !signature_to_verify) |
1142 | 0 | goto err; |
1143 | |
|
1144 | 0 | } else if (protocol == NID_id_TA_RSA_PSS_SHA_1 |
1145 | 0 | || protocol == NID_id_TA_RSA_PSS_SHA_256 |
1146 | 0 | || protocol == NID_id_TA_RSA_PSS_SHA_512) { |
1147 | 0 | if (!(type == EVP_PKEY_RSA)) |
1148 | 0 | goto err; |
1149 | | |
1150 | 0 | signature_to_verify = BUF_MEM_create_init(signature->data, signature->length); |
1151 | 0 | if (!EVP_PKEY_CTX_set_rsa_padding(tmp_key_ctx, RSA_PKCS1_PSS_PADDING) |
1152 | 0 | || !signature_to_verify) |
1153 | 0 | goto err; |
1154 | |
|
1155 | 0 | } else { |
1156 | 0 | goto err; |
1157 | 0 | } |
1158 | | |
1159 | | /* EVP_PKEY_sign doesn't perform hashing (despite EVP_PKEY_CTX_set_signature_md). |
1160 | | * Therefore we need to compute the hash ourself. */ |
1161 | 0 | verification_data = hash(md, NULL, NULL, data); |
1162 | 0 | if (!verification_data) |
1163 | 0 | goto err; |
1164 | | |
1165 | | /* Actual signature verification */ |
1166 | 0 | ret = EVP_PKEY_verify(tmp_key_ctx, (unsigned char*) signature_to_verify->data, |
1167 | 0 | signature_to_verify->length, (unsigned char*) verification_data->data, |
1168 | 0 | verification_data->length); |
1169 | |
|
1170 | 0 | err: |
1171 | 0 | if (verification_data) |
1172 | 0 | BUF_MEM_free(verification_data); |
1173 | 0 | if (signature_to_verify) |
1174 | 0 | BUF_MEM_free(signature_to_verify); |
1175 | 0 | if (tmp_key_ctx) |
1176 | 0 | EVP_PKEY_CTX_free(tmp_key_ctx); |
1177 | |
|
1178 | 0 | return ret; |
1179 | 0 | } |
1180 | | |
1181 | | BUF_MEM * |
1182 | | EAC_sign(int protocol, EVP_PKEY *key, const BUF_MEM *data) |
1183 | 0 | { |
1184 | 0 | BUF_MEM *signature = NULL, *signature_data = NULL, *plain_sig = NULL; |
1185 | 0 | EVP_PKEY_CTX *tmp_key_ctx = NULL; |
1186 | 0 | size_t len; |
1187 | 0 | const EVP_MD *md = eac_oid2md(protocol); |
1188 | 0 | int type; |
1189 | |
|
1190 | 0 | check((key && data), "Invalid arguments"); |
1191 | |
|
1192 | 0 | tmp_key_ctx = EVP_PKEY_CTX_new(key, NULL); |
1193 | 0 | if (!tmp_key_ctx || !md |
1194 | 0 | || EVP_PKEY_sign_init(tmp_key_ctx) <= 0 |
1195 | 0 | || EVP_PKEY_CTX_set_signature_md(tmp_key_ctx, md) <= 0) |
1196 | 0 | goto err; |
1197 | | |
1198 | | |
1199 | 0 | type = EVP_PKEY_base_id(key); |
1200 | 0 | if ( protocol == NID_id_TA_ECDSA_SHA_1 |
1201 | 0 | || protocol == NID_id_TA_ECDSA_SHA_224 |
1202 | 0 | || protocol == NID_id_TA_ECDSA_SHA_256 |
1203 | 0 | || protocol == NID_id_TA_ECDSA_SHA_384 |
1204 | 0 | || protocol == NID_id_TA_ECDSA_SHA_512) { |
1205 | 0 | if (!(type == EVP_PKEY_EC)) |
1206 | 0 | goto err; |
1207 | |
|
1208 | 0 | } else if (protocol == NID_id_TA_RSA_v1_5_SHA_1 |
1209 | 0 | || protocol == NID_id_TA_RSA_v1_5_SHA_256 |
1210 | 0 | || protocol == NID_id_TA_RSA_v1_5_SHA_512) { |
1211 | 0 | if (!(type == EVP_PKEY_RSA)) |
1212 | 0 | goto err; |
1213 | | |
1214 | 0 | if (!EVP_PKEY_CTX_set_rsa_padding(tmp_key_ctx, RSA_PKCS1_PADDING)) |
1215 | 0 | goto err; |
1216 | |
|
1217 | 0 | } else if (protocol == NID_id_TA_RSA_PSS_SHA_1 |
1218 | 0 | || protocol == NID_id_TA_RSA_PSS_SHA_256 |
1219 | 0 | || protocol == NID_id_TA_RSA_PSS_SHA_512) { |
1220 | 0 | if (!(type == EVP_PKEY_RSA)) |
1221 | 0 | goto err; |
1222 | | |
1223 | 0 | if (!EVP_PKEY_CTX_set_rsa_padding(tmp_key_ctx, RSA_PKCS1_PSS_PADDING)) |
1224 | 0 | goto err; |
1225 | |
|
1226 | 0 | } else { |
1227 | 0 | goto err; |
1228 | 0 | } |
1229 | | |
1230 | | /* EVP_PKEY_sign doesn't perform hashing (despite EVP_PKEY_CTX_set_signature_md). |
1231 | | * Therefore we need to compute the hash ourself. */ |
1232 | 0 | signature_data = hash(md, NULL, NULL, data); |
1233 | 0 | if (!signature_data) |
1234 | 0 | goto err; |
1235 | | |
1236 | | |
1237 | | /* Actual signature creation */ |
1238 | 0 | if (EVP_PKEY_sign(tmp_key_ctx, NULL, &len, |
1239 | 0 | (unsigned char*) signature_data->data, |
1240 | 0 | signature_data->length) <= 0) |
1241 | 0 | goto err; |
1242 | 0 | signature = BUF_MEM_create(len); |
1243 | 0 | if (!signature) |
1244 | 0 | goto err; |
1245 | 0 | if (EVP_PKEY_sign(tmp_key_ctx, |
1246 | 0 | (unsigned char *) signature->data, |
1247 | 0 | &signature->length, |
1248 | 0 | (unsigned char*) signature_data->data, |
1249 | 0 | signature_data->length) <= 0) |
1250 | 0 | goto err; |
1251 | | |
1252 | | |
1253 | | /* EAC signatures are always in plain signature format for EC curves but |
1254 | | * OpenSSL only creates X.509 format. Therefore we need to convert between |
1255 | | * these formats. */ |
1256 | 0 | if ( protocol == NID_id_TA_ECDSA_SHA_1 |
1257 | 0 | || protocol == NID_id_TA_ECDSA_SHA_224 |
1258 | 0 | || protocol == NID_id_TA_ECDSA_SHA_256 |
1259 | 0 | || protocol == NID_id_TA_ECDSA_SHA_384 |
1260 | 0 | || protocol == NID_id_TA_ECDSA_SHA_512) { |
1261 | 0 | plain_sig = convert_to_plain_sig(signature); |
1262 | 0 | BUF_MEM_free(signature); |
1263 | 0 | signature = plain_sig; |
1264 | 0 | } |
1265 | |
|
1266 | 0 | err: |
1267 | 0 | if (tmp_key_ctx) |
1268 | 0 | EVP_PKEY_CTX_free(tmp_key_ctx); |
1269 | 0 | if (signature_data) |
1270 | 0 | BUF_MEM_free(signature_data); |
1271 | |
|
1272 | 0 | return signature; |
1273 | 0 | } |