Return to gmp_rsa_public_key.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libstrongswan / plugins / gmp |
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: }