Return to gcrypt_rsa_public_key.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / strongswan / src / libstrongswan / plugins / gcrypt |
1.1 misho 1: /* 2: * Copyright (C) 2017 Tobias Brunner 3: * Copyright (C) 2005-2009 Martin Willi 4: * HSR Hochschule fuer Technik Rapperswil 5: * 6: * This program is free software; you can redistribute it and/or modify it 7: * under the terms of the GNU General Public License as published by the 8: * Free Software Foundation; either version 2 of the License, or (at your 9: * option) any later version. See <http://www.fsf.org/copyleft/gpl.txt>. 10: * 11: * This program is distributed in the hope that it will be useful, but 12: * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 13: * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14: * for more details. 15: */ 16: 17: #include <gcrypt.h> 18: 19: #include "gcrypt_rsa_public_key.h" 20: 21: #include <utils/debug.h> 22: #include <asn1/oid.h> 23: #include <asn1/asn1.h> 24: #include <asn1/asn1_parser.h> 25: #include <crypto/hashers/hasher.h> 26: #include <credentials/keys/signature_params.h> 27: 28: typedef struct private_gcrypt_rsa_public_key_t private_gcrypt_rsa_public_key_t; 29: 30: /** 31: * Private data structure with signing context. 32: */ 33: struct private_gcrypt_rsa_public_key_t { 34: 35: /** 36: * Public interface for this signer. 37: */ 38: gcrypt_rsa_public_key_t public; 39: 40: /** 41: * gcrypt S-expression representing an public RSA key 42: */ 43: gcry_sexp_t key; 44: 45: /** 46: * reference counter 47: */ 48: refcount_t ref; 49: }; 50: 51: /** 52: * Implemented in gcrypt_rsa_private_key.c 53: */ 54: chunk_t gcrypt_rsa_find_token(gcry_sexp_t sexp, char *name, gcry_sexp_t key); 55: 56: /** 57: * verification of a padded PKCS1 signature without an OID 58: */ 59: static bool verify_raw(private_gcrypt_rsa_public_key_t *this, 60: chunk_t data, chunk_t signature) 61: { 62: gcry_sexp_t in, sig; 63: gcry_error_t err; 64: chunk_t em; 65: size_t k; 66: 67: /* EM = 0x00 || 0x01 || PS || 0x00 || T 68: * PS = 0xFF padding, with length to fill em 69: * T = data 70: */ 71: k = gcry_pk_get_nbits(this->key) / 8; 72: if (data.len > k - 3) 73: { 74: return FALSE; 75: } 76: em = chunk_alloc(k); 77: memset(em.ptr, 0xFF, em.len); 78: em.ptr[0] = 0x00; 79: em.ptr[1] = 0x01; 80: em.ptr[em.len - data.len - 1] = 0x00; 81: memcpy(em.ptr + em.len - data.len, data.ptr, data.len); 82: 83: err = gcry_sexp_build(&in, NULL, "(data(flags raw)(value %b))", 84: em.len, em.ptr); 85: chunk_free(&em); 86: if (err) 87: { 88: DBG1(DBG_LIB, "building data S-expression failed: %s", 89: gpg_strerror(err)); 90: return FALSE; 91: } 92: err = gcry_sexp_build(&sig, NULL, "(sig-val(rsa(s %b)))", 93: signature.len, signature.ptr); 94: if (err) 95: { 96: DBG1(DBG_LIB, "building signature S-expression failed: %s", 97: gpg_strerror(err)); 98: gcry_sexp_release(in); 99: return FALSE; 100: } 101: err = gcry_pk_verify(sig, in, this->key); 102: gcry_sexp_release(in); 103: gcry_sexp_release(sig); 104: if (err) 105: { 106: DBG1(DBG_LIB, "RSA signature verification failed: %s", 107: gpg_strerror(err)); 108: return FALSE; 109: } 110: return TRUE; 111: } 112: 113: /** 114: * Verification of an EMSA PKCS1v1.5 / EMSA-PSS signature described in PKCS#1 115: */ 116: static bool verify_pkcs1(private_gcrypt_rsa_public_key_t *this, 117: hash_algorithm_t algorithm, rsa_pss_params_t *pss, 118: chunk_t data, chunk_t signature) 119: { 120: hasher_t *hasher; 121: chunk_t hash; 122: gcry_error_t err; 123: gcry_sexp_t in, sig; 124: char *hash_name = enum_to_name(hash_algorithm_short_names, algorithm); 125: 126: hasher = lib->crypto->create_hasher(lib->crypto, algorithm); 127: if (!hasher) 128: { 129: DBG1(DBG_LIB, "hash algorithm %N not supported", 130: hash_algorithm_names, algorithm); 131: return FALSE; 132: } 133: if (!hasher->allocate_hash(hasher, data, &hash)) 134: { 135: hasher->destroy(hasher); 136: return FALSE; 137: } 138: hasher->destroy(hasher); 139: 140: if (pss) 141: { 142: u_int slen = pss->salt_len; 143: err = gcry_sexp_build(&in, NULL, 144: "(data(flags pss)(salt-length %u)(hash %s %b))", 145: slen, hash_name, hash.len, hash.ptr); 146: } 147: else 148: { 149: err = gcry_sexp_build(&in, NULL, "(data(flags pkcs1)(hash %s %b))", 150: hash_name, hash.len, hash.ptr); 151: } 152: chunk_free(&hash); 153: if (err) 154: { 155: DBG1(DBG_LIB, "building data S-expression failed: %s", 156: gpg_strerror(err)); 157: return FALSE; 158: } 159: 160: err = gcry_sexp_build(&sig, NULL, "(sig-val(rsa(s %b)))", 161: signature.len, signature.ptr); 162: if (err) 163: { 164: DBG1(DBG_LIB, "building signature S-expression failed: %s", 165: gpg_strerror(err)); 166: gcry_sexp_release(in); 167: return FALSE; 168: } 169: err = gcry_pk_verify(sig, in, this->key); 170: gcry_sexp_release(in); 171: gcry_sexp_release(sig); 172: if (err) 173: { 174: DBG1(DBG_LIB, "RSA signature verification failed: %s", 175: gpg_strerror(err)); 176: return FALSE; 177: } 178: return TRUE; 179: } 180: 181: #if GCRYPT_VERSION_NUMBER >= 0x010700 182: /** 183: * Verification of an EMSA-PSS signature described in PKCS#1 184: */ 185: static bool verify_pss(private_gcrypt_rsa_public_key_t *this, 186: rsa_pss_params_t *params, chunk_t data, chunk_t sig) 187: { 188: if (!params) 189: { 190: return FALSE; 191: } 192: if (params->mgf1_hash != params->hash) 193: { 194: DBG1(DBG_LIB, "unable to use a different MGF1 hash for RSA-PSS"); 195: return FALSE; 196: } 197: return verify_pkcs1(this, params->hash, params, data, sig); 198: } 199: #endif 200: 201: METHOD(public_key_t, get_type, key_type_t, 202: private_gcrypt_rsa_public_key_t *this) 203: { 204: return KEY_RSA; 205: } 206: 207: METHOD(public_key_t, verify, bool, 208: private_gcrypt_rsa_public_key_t *this, signature_scheme_t scheme, 209: void *params, chunk_t data, chunk_t signature) 210: { 211: switch (scheme) 212: { 213: case SIGN_RSA_EMSA_PKCS1_NULL: 214: return verify_raw(this, data, signature); 215: case SIGN_RSA_EMSA_PKCS1_SHA2_224: 216: return verify_pkcs1(this, HASH_SHA224, NULL, data, signature); 217: case SIGN_RSA_EMSA_PKCS1_SHA2_256: 218: return verify_pkcs1(this, HASH_SHA256, NULL, data, signature); 219: case SIGN_RSA_EMSA_PKCS1_SHA2_384: 220: return verify_pkcs1(this, HASH_SHA384, NULL, data, signature); 221: case SIGN_RSA_EMSA_PKCS1_SHA2_512: 222: return verify_pkcs1(this, HASH_SHA512, NULL, data, signature); 223: case SIGN_RSA_EMSA_PKCS1_SHA1: 224: return verify_pkcs1(this, HASH_SHA1, NULL, data, signature); 225: case SIGN_RSA_EMSA_PKCS1_MD5: 226: return verify_pkcs1(this, HASH_MD5, NULL, data, signature); 227: #if GCRYPT_VERSION_NUMBER >= 0x010700 228: case SIGN_RSA_EMSA_PSS: 229: return verify_pss(this, params, data, signature); 230: #endif 231: default: 232: DBG1(DBG_LIB, "signature scheme %N not supported in RSA", 233: signature_scheme_names, scheme); 234: return FALSE; 235: } 236: } 237: 238: METHOD(public_key_t, encrypt_, bool, 239: private_gcrypt_rsa_public_key_t *this, encryption_scheme_t scheme, 240: chunk_t plain, chunk_t *encrypted) 241: { 242: gcry_sexp_t in, out; 243: gcry_error_t err; 244: 245: if (scheme != ENCRYPT_RSA_PKCS1) 246: { 247: DBG1(DBG_LIB, "encryption scheme %N not supported", 248: encryption_scheme_names, scheme); 249: return FALSE; 250: } 251: /* "pkcs1" uses PKCS 1.5 (section 8.1) block type 2 encryption: 252: * 00 | 02 | RANDOM | 00 | DATA */ 253: err = gcry_sexp_build(&in, NULL, "(data(flags pkcs1)(value %b))", 254: plain.len, plain.ptr); 255: if (err) 256: { 257: DBG1(DBG_LIB, "building encryption S-expression failed: %s", 258: gpg_strerror(err)); 259: return FALSE; 260: } 261: err = gcry_pk_encrypt(&out, in, this->key); 262: gcry_sexp_release(in); 263: if (err) 264: { 265: DBG1(DBG_LIB, "encrypting data using pkcs1 failed: %s", 266: gpg_strerror(err)); 267: return FALSE; 268: } 269: *encrypted = gcrypt_rsa_find_token(out, "a", this->key); 270: gcry_sexp_release(out); 271: return !!encrypted->len; 272: } 273: 274: METHOD(public_key_t, get_keysize, int, 275: private_gcrypt_rsa_public_key_t *this) 276: { 277: return gcry_pk_get_nbits(this->key); 278: } 279: 280: METHOD(public_key_t, get_encoding, bool, 281: private_gcrypt_rsa_public_key_t *this, cred_encoding_type_t type, 282: chunk_t *encoding) 283: { 284: chunk_t n, e; 285: bool success; 286: 287: n = gcrypt_rsa_find_token(this->key, "n", NULL); 288: e = gcrypt_rsa_find_token(this->key, "e", NULL); 289: success = lib->encoding->encode(lib->encoding, type, NULL, encoding, 290: CRED_PART_RSA_MODULUS, n, CRED_PART_RSA_PUB_EXP, e, 291: CRED_PART_END); 292: chunk_free(&n); 293: chunk_free(&e); 294: 295: return success; 296: } 297: 298: METHOD(public_key_t, get_fingerprint, bool, 299: private_gcrypt_rsa_public_key_t *this, cred_encoding_type_t type, 300: chunk_t *fp) 301: { 302: chunk_t n, e; 303: bool success; 304: 305: if (lib->encoding->get_cache(lib->encoding, type, this, fp)) 306: { 307: return TRUE; 308: } 309: n = gcrypt_rsa_find_token(this->key, "n", NULL); 310: e = gcrypt_rsa_find_token(this->key, "e", NULL); 311: 312: success = lib->encoding->encode(lib->encoding, 313: type, this, fp, CRED_PART_RSA_MODULUS, n, 314: CRED_PART_RSA_PUB_EXP, e, CRED_PART_END); 315: chunk_free(&n); 316: chunk_free(&e); 317: return success; 318: } 319: 320: METHOD(public_key_t, get_ref, public_key_t*, 321: private_gcrypt_rsa_public_key_t *this) 322: { 323: ref_get(&this->ref); 324: return &this->public.key; 325: } 326: 327: METHOD(public_key_t, destroy, void, 328: private_gcrypt_rsa_public_key_t *this) 329: { 330: if (ref_put(&this->ref)) 331: { 332: gcry_sexp_release(this->key); 333: lib->encoding->clear_cache(lib->encoding, this); 334: free(this); 335: } 336: } 337: 338: /** 339: * See header. 340: */ 341: gcrypt_rsa_public_key_t *gcrypt_rsa_public_key_load(key_type_t type, 342: va_list args) 343: { 344: private_gcrypt_rsa_public_key_t *this; 345: gcry_error_t err; 346: chunk_t n, e; 347: 348: n = e = chunk_empty; 349: while (TRUE) 350: { 351: switch (va_arg(args, builder_part_t)) 352: { 353: case BUILD_RSA_MODULUS: 354: n = va_arg(args, chunk_t); 355: continue; 356: case BUILD_RSA_PUB_EXP: 357: e = va_arg(args, chunk_t); 358: continue; 359: case BUILD_END: 360: break; 361: default: 362: return NULL; 363: } 364: break; 365: } 366: 367: INIT(this, 368: .public = { 369: .key = { 370: .get_type = _get_type, 371: .verify = _verify, 372: .encrypt = _encrypt_, 373: .equals = public_key_equals, 374: .get_keysize = _get_keysize, 375: .get_fingerprint = _get_fingerprint, 376: .has_fingerprint = public_key_has_fingerprint, 377: .get_encoding = _get_encoding, 378: .get_ref = _get_ref, 379: .destroy = _destroy, 380: }, 381: }, 382: .ref = 1, 383: ); 384: 385: err = gcry_sexp_build(&this->key, NULL, "(public-key(rsa(n %b)(e %b)))", 386: n.len, n.ptr, e.len, e.ptr); 387: if (err) 388: { 389: DBG1(DBG_LIB, "loading public key failed: %s", gpg_strerror(err)); 390: free(this); 391: return NULL; 392: } 393: 394: return &this->public; 395: } 396: