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>