Annotation of embedaddon/strongswan/src/libstrongswan/plugins/gmp/gmp_rsa_public_key.c, revision 1.1.1.1
1.1 misho 1: /*
2: * Copyright (C) 2017-2018 Tobias Brunner
3: * Copyright (C) 2005-2009 Martin Willi
4: * Copyright (C) 2005 Jan Hutter
5: * HSR Hochschule fuer Technik Rapperswil
6: *
7: * This program is free software; you can redistribute it and/or modify it
8: * under the terms of the GNU General Public License as published by the
9: * Free Software Foundation; either version 2 of the License, or (at your
10: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>.
11: *
12: * This program is distributed in the hope that it will be useful, but
13: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
15: * for more details.
16: */
17:
18: #include <gmp.h>
19: #include <sys/stat.h>
20: #include <unistd.h>
21: #include <stdio.h>
22: #include <string.h>
23:
24: #include "gmp_rsa_public_key.h"
25:
26: #include <utils/debug.h>
27: #include <asn1/oid.h>
28: #include <asn1/asn1.h>
29: #include <asn1/asn1_parser.h>
30: #include <crypto/hashers/hasher.h>
31: #include <credentials/keys/signature_params.h>
32:
33: #ifdef HAVE_MPZ_POWM_SEC
34: # undef mpz_powm
35: # define mpz_powm mpz_powm_sec
36: #endif
37:
38: typedef struct private_gmp_rsa_public_key_t private_gmp_rsa_public_key_t;
39:
40: /**
41: * Private data structure with signing context.
42: */
43: struct private_gmp_rsa_public_key_t {
44: /**
45: * Public interface for this signer.
46: */
47: gmp_rsa_public_key_t public;
48:
49: /**
50: * Public modulus.
51: */
52: mpz_t n;
53:
54: /**
55: * Public exponent.
56: */
57: mpz_t e;
58:
59: /**
60: * Keysize in bytes.
61: */
62: size_t k;
63:
64: /**
65: * reference counter
66: */
67: refcount_t ref;
68: };
69:
70: /**
71: * Shared functions defined in gmp_rsa_private_key.c
72: */
73: chunk_t gmp_mpz_to_chunk(const mpz_t value);
74: bool gmp_emsa_pkcs1_signature_data(hash_algorithm_t hash_algorithm,
75: chunk_t data, size_t keylen, chunk_t *em);
76:
77: /**
78: * RSAEP algorithm specified in PKCS#1.
79: */
80: static chunk_t rsaep(private_gmp_rsa_public_key_t *this, chunk_t data)
81: {
82: mpz_t m, c;
83: chunk_t encrypted;
84:
85: mpz_init(m);
86: mpz_import(m, data.len, 1, 1, 1, 0, data.ptr);
87:
88: if (mpz_cmp_ui(m, 0) <= 0 || mpz_cmp(m, this->n) >= 0)
89: { /* m must be <= n-1, and while 0 is technically a valid value, it
90: * doesn't really make sense here, so we filter that too */
91: mpz_clear(m);
92: return chunk_empty;
93: }
94:
95: mpz_init(c);
96: mpz_powm(c, m, this->e, this->n);
97:
98: encrypted.len = this->k;
99: encrypted.ptr = mpz_export(NULL, NULL, 1, encrypted.len, 1, 0, c);
100: if (encrypted.ptr == NULL)
101: {
102: encrypted.len = 0;
103: }
104:
105: mpz_clear(c);
106: mpz_clear(m);
107:
108: return encrypted;
109: }
110:
111: /**
112: * RSAVP1 algorithm specified in PKCS#1.
113: */
114: static chunk_t rsavp1(private_gmp_rsa_public_key_t *this, chunk_t data)
115: {
116: return rsaep(this, data);
117: }
118:
119: /**
120: * Verification of an EMSA PKCS1 signature described in PKCS#1
121: */
122: static bool verify_emsa_pkcs1_signature(private_gmp_rsa_public_key_t *this,
123: hash_algorithm_t algorithm,
124: chunk_t data, chunk_t signature)
125: {
126: chunk_t em_expected, em;
127: bool success = FALSE;
128:
129: /* remove any preceding 0-bytes from signature */
130: while (signature.len && *(signature.ptr) == 0x00)
131: {
132: signature = chunk_skip(signature, 1);
133: }
134:
135: if (signature.len == 0 || signature.len > this->k)
136: {
137: return FALSE;
138: }
139:
140: /* generate expected signature value */
141: if (!gmp_emsa_pkcs1_signature_data(algorithm, data, this->k, &em_expected))
142: {
143: return FALSE;
144: }
145:
146: /* unpack signature */
147: em = rsavp1(this, signature);
148:
149: success = chunk_equals_const(em_expected, em);
150:
151: chunk_free(&em_expected);
152: chunk_free(&em);
153: return success;
154: }
155:
156: /**
157: * Verification of an EMSA PSS signature described in PKCS#1
158: */
159: static bool verify_emsa_pss_signature(private_gmp_rsa_public_key_t *this,
160: rsa_pss_params_t *params, chunk_t data,
161: chunk_t signature)
162: {
163: ext_out_function_t xof;
164: hasher_t *hasher = NULL;
165: xof_t *mgf = NULL;
166: chunk_t em, hash, salt, db, h, dbmask, m;
167: size_t embits, maskbits;
168: int i;
169: bool success = FALSE;
170:
171: if (!params)
172: {
173: return FALSE;
174: }
175: xof = xof_mgf1_from_hash_algorithm(params->mgf1_hash);
176: if (xof == XOF_UNDEFINED)
177: {
178: DBG1(DBG_LIB, "%N is not supported for MGF1", hash_algorithm_names,
179: params->mgf1_hash);
180: return FALSE;
181: }
182: chunk_skip_zero(signature);
183: if (signature.len == 0 || signature.len > this->k)
184: {
185: return FALSE;
186: }
187: /* EM = RSAVP1((n, e), S) */
188: em = rsavp1(this, signature);
189: if (!em.len)
190: {
191: goto error;
192: }
193: /* emBits = modBits - 1 */
194: embits = mpz_sizeinbase(this->n, 2) - 1;
195: /* mHash = Hash(M) */
196: hasher = lib->crypto->create_hasher(lib->crypto, params->hash);
197: if (!hasher)
198: {
199: DBG1(DBG_LIB, "hash algorithm %N not supported",
200: hash_algorithm_names, params->hash);
201: goto error;
202: }
203: hash = chunk_alloca(hasher->get_hash_size(hasher));
204: if (!hasher->get_hash(hasher, data, hash.ptr))
205: {
206: goto error;
207: }
208: salt.len = params->salt_len;
209: /* verify general structure of EM */
210: maskbits = (8 * em.len) - embits;
211: if (em.len < (hash.len + salt.len + 2) || em.ptr[em.len-1] != 0xbc ||
212: (em.ptr[0] & (0xff << (8-maskbits))))
213: { /* inconsistent */
214: goto error;
215: }
216: /* split EM in maskedDB and H */
217: db = chunk_create(em.ptr, em.len - hash.len - 1);
218: h = chunk_create(em.ptr + db.len, hash.len);
219: /* dbMask = MGF(H, emLen - hLen - 1) */
220: mgf = lib->crypto->create_xof(lib->crypto, xof);
221: if (!mgf)
222: {
223: DBG1(DBG_LIB, "%N not supported", ext_out_function_names, xof);
224: goto error;
225: }
226: dbmask = chunk_alloca(db.len);
227: if (!mgf->set_seed(mgf, h) ||
228: !mgf->get_bytes(mgf, dbmask.len, dbmask.ptr))
229: {
230: DBG1(DBG_LIB, "%N not supported or failed", ext_out_function_names, xof);
231: goto error;
232: }
233: /* DB = maskedDB xor dbMask */
234: memxor(db.ptr, dbmask.ptr, db.len);
235: if (maskbits)
236: {
237: db.ptr[0] &= (0xff >> maskbits);
238: }
239: /* check DB = PS | 0x01 | salt */
240: for (i = 0; i < (db.len - salt.len - 1); i++)
241: {
242: if (db.ptr[i])
243: { /* padding not 0 */
244: goto error;
245: }
246: }
247: if (db.ptr[i++] != 0x01)
248: { /* 0x01 not found */
249: goto error;
250: }
251: salt.ptr = &db.ptr[i];
252: /* M' = 0x0000000000000000 | mHash | salt */
253: m = chunk_cata("ccc",
254: chunk_from_chars(0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00),
255: hash, salt);
256: if (!hasher->get_hash(hasher, m, hash.ptr))
257: {
258: goto error;
259: }
260: success = memeq_const(h.ptr, hash.ptr, hash.len);
261:
262: error:
263: DESTROY_IF(hasher);
264: DESTROY_IF(mgf);
265: free(em.ptr);
266: return success;
267: }
268:
269: METHOD(public_key_t, get_type, key_type_t,
270: private_gmp_rsa_public_key_t *this)
271: {
272: return KEY_RSA;
273: }
274:
275: METHOD(public_key_t, verify, bool,
276: private_gmp_rsa_public_key_t *this, signature_scheme_t scheme, void *params,
277: chunk_t data, chunk_t signature)
278: {
279: switch (scheme)
280: {
281: case SIGN_RSA_EMSA_PKCS1_NULL:
282: return verify_emsa_pkcs1_signature(this, HASH_UNKNOWN, data, signature);
283: case SIGN_RSA_EMSA_PKCS1_SHA2_224:
284: return verify_emsa_pkcs1_signature(this, HASH_SHA224, data, signature);
285: case SIGN_RSA_EMSA_PKCS1_SHA2_256:
286: return verify_emsa_pkcs1_signature(this, HASH_SHA256, data, signature);
287: case SIGN_RSA_EMSA_PKCS1_SHA2_384:
288: return verify_emsa_pkcs1_signature(this, HASH_SHA384, data, signature);
289: case SIGN_RSA_EMSA_PKCS1_SHA2_512:
290: return verify_emsa_pkcs1_signature(this, HASH_SHA512, data, signature);
291: case SIGN_RSA_EMSA_PKCS1_SHA3_224:
292: return verify_emsa_pkcs1_signature(this, HASH_SHA3_224, data, signature);
293: case SIGN_RSA_EMSA_PKCS1_SHA3_256:
294: return verify_emsa_pkcs1_signature(this, HASH_SHA3_256, data, signature);
295: case SIGN_RSA_EMSA_PKCS1_SHA3_384:
296: return verify_emsa_pkcs1_signature(this, HASH_SHA3_384, data, signature);
297: case SIGN_RSA_EMSA_PKCS1_SHA3_512:
298: return verify_emsa_pkcs1_signature(this, HASH_SHA3_512, data, signature);
299: case SIGN_RSA_EMSA_PKCS1_SHA1:
300: return verify_emsa_pkcs1_signature(this, HASH_SHA1, data, signature);
301: case SIGN_RSA_EMSA_PKCS1_MD5:
302: return verify_emsa_pkcs1_signature(this, HASH_MD5, data, signature);
303: case SIGN_RSA_EMSA_PSS:
304: return verify_emsa_pss_signature(this, params, data, signature);
305: default:
306: DBG1(DBG_LIB, "signature scheme %N not supported in RSA",
307: signature_scheme_names, scheme);
308: return FALSE;
309: }
310: }
311:
312: #define MIN_PS_PADDING 8
313:
314: METHOD(public_key_t, encrypt_, bool,
315: private_gmp_rsa_public_key_t *this, encryption_scheme_t scheme,
316: chunk_t plain, chunk_t *crypto)
317: {
318: chunk_t em;
319: u_char *pos;
320: int padding;
321: rng_t *rng;
322:
323: if (scheme != ENCRYPT_RSA_PKCS1)
324: {
325: DBG1(DBG_LIB, "encryption scheme %N not supported",
326: encryption_scheme_names, scheme);
327: return FALSE;
328: }
329: /* number of pseudo-random padding octets */
330: padding = this->k - plain.len - 3;
331: if (padding < MIN_PS_PADDING)
332: {
333: DBG1(DBG_LIB, "pseudo-random padding must be at least %d octets",
334: MIN_PS_PADDING);
335: return FALSE;
336: }
337: rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
338: if (rng == NULL)
339: {
340: DBG1(DBG_LIB, "no random generator available");
341: return FALSE;
342: }
343:
344: /* padding according to PKCS#1 7.2.1 (RSAES-PKCS1-v1.5-ENCRYPT) */
345: DBG2(DBG_LIB, "padding %u bytes of data to the rsa modulus size of"
346: " %u bytes", plain.len, this->k);
347: em.len = this->k;
348: em.ptr = malloc(em.len);
349: pos = em.ptr;
350: *pos++ = 0x00;
351: *pos++ = 0x02;
352:
353: /* fill with pseudo random octets */
354: if (!rng_get_bytes_not_zero(rng, padding, pos, TRUE))
355: {
356: DBG1(DBG_LIB, "failed to allocate padding");
357: chunk_clear(&em);
358: rng->destroy(rng);
359: return FALSE;
360: }
361: rng->destroy(rng);
362:
363: pos += padding;
364:
365: /* append the padding terminator */
366: *pos++ = 0x00;
367:
368: /* now add the data */
369: memcpy(pos, plain.ptr, plain.len);
370: DBG3(DBG_LIB, "padded data before rsa encryption: %B", &em);
371:
372: /* rsa encryption using PKCS#1 RSAEP */
373: *crypto = rsaep(this, em);
374: DBG3(DBG_LIB, "rsa encrypted data: %B", crypto);
375: chunk_clear(&em);
376: return TRUE;
377: }
378:
379: METHOD(public_key_t, get_keysize, int,
380: private_gmp_rsa_public_key_t *this)
381: {
382: return mpz_sizeinbase(this->n, 2);
383: }
384:
385: METHOD(public_key_t, get_encoding, bool,
386: private_gmp_rsa_public_key_t *this, cred_encoding_type_t type,
387: chunk_t *encoding)
388: {
389: chunk_t n, e;
390: bool success;
391:
392: n = gmp_mpz_to_chunk(this->n);
393: e = gmp_mpz_to_chunk(this->e);
394:
395: success = lib->encoding->encode(lib->encoding, type, NULL, encoding,
396: CRED_PART_RSA_MODULUS, n, CRED_PART_RSA_PUB_EXP, e, CRED_PART_END);
397: chunk_free(&n);
398: chunk_free(&e);
399:
400: return success;
401: }
402:
403: METHOD(public_key_t, get_fingerprint, bool,
404: private_gmp_rsa_public_key_t *this, cred_encoding_type_t type, chunk_t *fp)
405: {
406: chunk_t n, e;
407: bool success;
408:
409: if (lib->encoding->get_cache(lib->encoding, type, this, fp))
410: {
411: return TRUE;
412: }
413: n = gmp_mpz_to_chunk(this->n);
414: e = gmp_mpz_to_chunk(this->e);
415:
416: success = lib->encoding->encode(lib->encoding, type, this, fp,
417: CRED_PART_RSA_MODULUS, n, CRED_PART_RSA_PUB_EXP, e, CRED_PART_END);
418: chunk_free(&n);
419: chunk_free(&e);
420:
421: return success;
422: }
423:
424: METHOD(public_key_t, get_ref, public_key_t*,
425: private_gmp_rsa_public_key_t *this)
426: {
427: ref_get(&this->ref);
428: return &this->public.key;
429: }
430:
431: METHOD(public_key_t, destroy, void,
432: private_gmp_rsa_public_key_t *this)
433: {
434: if (ref_put(&this->ref))
435: {
436: mpz_clear(this->n);
437: mpz_clear(this->e);
438: lib->encoding->clear_cache(lib->encoding, this);
439: free(this);
440: }
441: }
442:
443: /**
444: * See header.
445: */
446: gmp_rsa_public_key_t *gmp_rsa_public_key_load(key_type_t type, va_list args)
447: {
448: private_gmp_rsa_public_key_t *this;
449: chunk_t n, e;
450:
451: n = e = chunk_empty;
452: while (TRUE)
453: {
454: switch (va_arg(args, builder_part_t))
455: {
456: case BUILD_RSA_MODULUS:
457: n = va_arg(args, chunk_t);
458: continue;
459: case BUILD_RSA_PUB_EXP:
460: e = va_arg(args, chunk_t);
461: continue;
462: case BUILD_END:
463: break;
464: default:
465: return NULL;
466: }
467: break;
468: }
469: if (!e.len || !n.len || (n.ptr[n.len-1] & 0x01) == 0)
470: {
471: return NULL;
472: }
473:
474: INIT(this,
475: .public = {
476: .key = {
477: .get_type = _get_type,
478: .verify = _verify,
479: .encrypt = _encrypt_,
480: .equals = public_key_equals,
481: .get_keysize = _get_keysize,
482: .get_fingerprint = _get_fingerprint,
483: .has_fingerprint = public_key_has_fingerprint,
484: .get_encoding = _get_encoding,
485: .get_ref = _get_ref,
486: .destroy = _destroy,
487: },
488: },
489: .ref = 1,
490: );
491:
492: mpz_init(this->n);
493: mpz_init(this->e);
494:
495: mpz_import(this->n, n.len, 1, 1, 1, 0, n.ptr);
496: mpz_import(this->e, e.len, 1, 1, 1, 0, e.ptr);
497:
498: this->k = (mpz_sizeinbase(this->n, 2) + 7) / BITS_PER_BYTE;
499:
500: if (!mpz_sgn(this->e))
501: {
502: destroy(this);
503: return NULL;
504: }
505: return &this->public;
506: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>