Annotation of embedaddon/strongswan/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_public_key.c, revision 1.1
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:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>