Annotation of embedaddon/strongswan/src/libstrongswan/plugins/gcrypt/gcrypt_rsa_public_key.c, revision 1.1.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>