Annotation of embedaddon/strongswan/src/libstrongswan/credentials/keys/signature_params.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2017 Tobias Brunner
                      3:  * HSR Hochschule fuer Technik Rapperswil
                      4:  *
                      5:  * This program is free software; you can redistribute it and/or modify it
                      6:  * under the terms of the GNU General Public License as published by the
                      7:  * Free Software Foundation; either version 2 of the License, or (at your
                      8:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                      9:  *
                     10:  * This program is distributed in the hope that it will be useful, but
                     11:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     12:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     13:  * for more details.
                     14:  */
                     15: 
                     16: #include "signature_params.h"
                     17: 
                     18: #include <asn1/oid.h>
                     19: #include <asn1/asn1_parser.h>
                     20: 
                     21: /*
                     22:  * Described in header
                     23:  */
                     24: bool rsa_pss_params_set_salt_len(rsa_pss_params_t *params, size_t modbits)
                     25: {
                     26:        size_t hash_len;
                     27: 
                     28:        if (params->salt_len < 0)
                     29:        {
                     30:                hash_len = hasher_hash_size(params->hash);
                     31:                if (!hash_len)
                     32:                {
                     33:                        return FALSE;
                     34:                }
                     35: 
                     36:                switch (params->salt_len)
                     37:                {
                     38:                        case RSA_PSS_SALT_LEN_DEFAULT:
                     39:                                params->salt_len = hash_len;
                     40:                                break;
                     41:                        case RSA_PSS_SALT_LEN_MAX:
                     42:                                if (modbits)
                     43:                                {
                     44:                                        /* emBits = modBits - 1 */
                     45:                                        modbits -= 1;
                     46:                                        /* emLen = ceil(emBits/8) */
                     47:                                        modbits = (modbits+7) / BITS_PER_BYTE;
                     48:                                        /* account for 0x01 separator in DB, 0xbc trailing byte */
                     49:                                        params->salt_len = max(0, (ssize_t)(modbits - hash_len - 2));
                     50:                                        break;
                     51:                                }
                     52:                                return FALSE;
                     53:                        default:
                     54:                                return FALSE;
                     55:                }
                     56:        }
                     57:        return TRUE;
                     58: }
                     59: 
                     60: /**
                     61:  * Compare two signature schemes and their parameters
                     62:  */
                     63: static bool compare_params(signature_params_t *a, signature_params_t *b,
                     64:                                                   bool strict)
                     65: {
                     66:        if (!a && !b)
                     67:        {
                     68:                return TRUE;
                     69:        }
                     70:        if (!a || !b)
                     71:        {
                     72:                return FALSE;
                     73:        }
                     74:        if (a->scheme != b->scheme)
                     75:        {
                     76:                return FALSE;
                     77:        }
                     78:        if (!a->params && !b->params)
                     79:        {
                     80:                return TRUE;
                     81:        }
                     82:        if (a->params && b->params)
                     83:        {
                     84:                switch (a->scheme)
                     85:                {
                     86:                        case SIGN_RSA_EMSA_PSS:
                     87:                        {
                     88:                                rsa_pss_params_t *pss_a = a->params, *pss_b = b->params;
                     89: 
                     90:                                return pss_a->hash == pss_b->hash &&
                     91:                                           pss_a->mgf1_hash == pss_b->mgf1_hash &&
                     92:                                           (!strict || pss_a->salt_len == pss_b->salt_len);
                     93:                        }
                     94:                        default:
                     95:                                break;
                     96:                }
                     97:        }
                     98:        return FALSE;
                     99: }
                    100: 
                    101: /*
                    102:  * Described in header
                    103:  */
                    104: bool signature_params_equal(signature_params_t *a, signature_params_t *b)
                    105: {
                    106:        return compare_params(a, b, TRUE);
                    107: }
                    108: 
                    109: /*
                    110:  * Described in header
                    111:  */
                    112: bool signature_params_comply(signature_params_t *c, signature_params_t *s)
                    113: {      /* the salt is variable, so it does not necessarily have to be the same */
                    114:        return compare_params(c, s, FALSE);
                    115: }
                    116: 
                    117: /*
                    118:  * Described in header
                    119:  */
                    120: signature_params_t *signature_params_clone(signature_params_t *this)
                    121: {
                    122:        signature_params_t *clone;
                    123: 
                    124:        if (!this)
                    125:        {
                    126:                return NULL;
                    127:        }
                    128: 
                    129:        INIT(clone,
                    130:                .scheme = this->scheme,
                    131:        );
                    132:        if (this->params)
                    133:        {
                    134:                switch (this->scheme)
                    135:                {
                    136:                        case SIGN_RSA_EMSA_PSS:
                    137:                        {
                    138:                                rsa_pss_params_t *pss, *pss_clone;
                    139: 
                    140:                                pss = this->params;
                    141:                                INIT(pss_clone,
                    142:                                        .hash = pss->hash,
                    143:                                        .mgf1_hash = pss->mgf1_hash,
                    144:                                        .salt_len = pss->salt_len,
                    145:                                        /* ignore salt as only used for unit tests */
                    146:                                );
                    147:                                clone->params = pss_clone;
                    148:                                break;
                    149:                        }
                    150:                        default:
                    151:                                break;
                    152:                }
                    153:        }
                    154:        return clone;
                    155: }
                    156: 
                    157: /*
                    158:  * Described in header
                    159:  */
                    160: void signature_params_destroy(signature_params_t *this)
                    161: {
                    162:        if (this)
                    163:        {
                    164:                free(this->params);
                    165:                free(this);
                    166:        }
                    167: }
                    168: 
                    169: /*
                    170:  * Described in header
                    171:  */
                    172: void signature_params_clear(signature_params_t *this)
                    173: {
                    174:        if (this)
                    175:        {
                    176:                free(this->params);
                    177:                this->params = NULL;
                    178:                this->scheme = SIGN_UNKNOWN;
                    179:        }
                    180: }
                    181: 
                    182: /*
                    183:  * Described in header
                    184:  */
                    185: bool signature_params_parse(chunk_t asn1, int level0,
                    186:                                                        signature_params_t *params)
                    187: {
                    188:        chunk_t parameters = chunk_empty;
                    189:        int oid;
                    190: 
                    191:        oid = asn1_parse_algorithmIdentifier(asn1, level0, &parameters);
                    192:        params->scheme = signature_scheme_from_oid(oid);
                    193:        switch (params->scheme)
                    194:        {
                    195:                case SIGN_UNKNOWN:
                    196:                        return FALSE;
                    197:                case SIGN_RSA_EMSA_PSS:
                    198:                {
                    199:                        rsa_pss_params_t *pss = malloc_thing(rsa_pss_params_t);
                    200: 
                    201:                        if (!rsa_pss_params_parse(parameters, level0+1, pss))
                    202:                        {
                    203:                                DBG1(DBG_IKE, "failed parsing RSASSA-PSS parameters");
                    204:                                free(pss);
                    205:                                return FALSE;
                    206:                        }
                    207:                        params->params = pss;
                    208:                        break;
                    209:                }
                    210:                default:
                    211:                        params->params = NULL;
                    212:                        break;
                    213:        }
                    214:        return TRUE;
                    215: }
                    216: 
                    217: /*
                    218:  * Described in header
                    219:  */
                    220: bool signature_params_build(signature_params_t *params, chunk_t *asn1)
                    221: {
                    222:        chunk_t parameters = chunk_empty;
                    223:        int oid;
                    224: 
                    225:        oid = signature_scheme_to_oid(params->scheme);
                    226:        if (oid == OID_UNKNOWN)
                    227:        {
                    228:                return FALSE;
                    229:        }
                    230:        if (params->scheme == SIGN_RSA_EMSA_PSS &&
                    231:                !rsa_pss_params_build(params->params, &parameters))
                    232:        {
                    233:                return FALSE;
                    234:        }
                    235:        if (parameters.len)
                    236:        {
                    237:                *asn1 = asn1_algorithmIdentifier_params(oid, parameters);
                    238:        }
                    239:        else
                    240:        {
                    241:                *asn1 = asn1_algorithmIdentifier(oid);
                    242:        }
                    243:        return TRUE;
                    244: }
                    245: 
                    246: /**
                    247:  * ASN.1 definition of RSASSA-PSS-params
                    248:  */
                    249: static const asn1Object_t RSASSAPSSParamsObjects[] = {
                    250:        { 0, "RSASSA-PSS-params",       ASN1_SEQUENCE,          ASN1_NONE                       }, /* 0 */
                    251:        { 1,   "DEFAULT SHA-1",         ASN1_CONTEXT_C_0,       ASN1_DEF                        }, /* 1 */
                    252:        { 2,     "hashAlgorithm",       ASN1_EOC,                       ASN1_RAW                        }, /* 2 */
                    253:        { 1,   "DEFAULT MGF1SHA1",      ASN1_CONTEXT_C_1,       ASN1_DEF                        }, /* 3 */
                    254:        { 2,     "maskGenAlgorithm",ASN1_EOC,                   ASN1_RAW                        }, /* 4 */
                    255:        { 1,   "DEFAULT 20",            ASN1_CONTEXT_C_2,       ASN1_DEF                        }, /* 5 */
                    256:        { 2,     "saltLength",          ASN1_INTEGER,           ASN1_BODY                       }, /* 6 */
                    257:        { 1,   "DEFAULT 1",                     ASN1_CONTEXT_C_3,       ASN1_DEF                        }, /* 7 */
                    258:        { 2,     "trailerField",        ASN1_INTEGER,           ASN1_BODY                       }, /* 8 */
                    259:        { 0, "exit",                            ASN1_EOC,                       ASN1_EXIT                       }
                    260: };
                    261: #define RSASSA_PSS_PARAMS_HASH_ALG             2
                    262: #define RSASSA_PSS_PARAMS_MGF_ALG              4
                    263: #define RSASSA_PSS_PARAMS_SALT_LEN             6
                    264: #define RSASSA_PSS_PARAMS_TRAILER              8
                    265: 
                    266: /*
                    267:  * Described in header
                    268:  */
                    269: bool rsa_pss_params_parse(chunk_t asn1, int level0, rsa_pss_params_t *params)
                    270: {
                    271:        asn1_parser_t *parser;
                    272:        chunk_t object;
                    273:        int objectID, alg;
                    274:        bool success = FALSE;
                    275: 
                    276:        params->hash = HASH_SHA1;
                    277:        params->mgf1_hash = HASH_SHA1;
                    278:        params->salt_len = HASH_SIZE_SHA1;
                    279: 
                    280:        parser = asn1_parser_create(RSASSAPSSParamsObjects, asn1);
                    281:        parser->set_top_level(parser, level0);
                    282: 
                    283:        while (parser->iterate(parser, &objectID, &object))
                    284:        {
                    285:                u_int level = parser->get_level(parser)+1;
                    286: 
                    287:                switch (objectID)
                    288:                {
                    289:                        case RSASSA_PSS_PARAMS_HASH_ALG:
                    290:                                if (object.len)
                    291:                                {
                    292:                                        alg = asn1_parse_algorithmIdentifier(object, level, NULL);
                    293:                                        params->hash = hasher_algorithm_from_oid(alg);
                    294:                                        if (params->hash == HASH_UNKNOWN)
                    295:                                        {
                    296:                                                goto end;
                    297:                                        }
                    298:                                }
                    299:                                break;
                    300:                        case RSASSA_PSS_PARAMS_MGF_ALG:
                    301:                                if (object.len)
                    302:                                {
                    303:                                        chunk_t hash = chunk_empty;
                    304: 
                    305:                                        alg = asn1_parse_algorithmIdentifier(object, level, &hash);
                    306:                                        if (alg != OID_MGF1)
                    307:                                        {
                    308:                                                goto end;
                    309:                                        }
                    310:                                        if (!hash.len)
                    311:                                        {
                    312:                                                goto end;
                    313:                                        }
                    314:                                        alg = asn1_parse_algorithmIdentifier(hash, level+1, NULL);
                    315:                                        params->mgf1_hash = hasher_algorithm_from_oid(alg);
                    316:                                        if (params->mgf1_hash == HASH_UNKNOWN)
                    317:                                        {
                    318:                                                goto end;
                    319:                                        }
                    320:                                }
                    321:                                break;
                    322:                        case RSASSA_PSS_PARAMS_SALT_LEN:
                    323:                                if (object.len)
                    324:                                {
                    325:                                        params->salt_len = (size_t)asn1_parse_integer_uint64(object);
                    326:                                }
                    327:                                break;
                    328:                        case RSASSA_PSS_PARAMS_TRAILER:
                    329:                                if (object.len && (object.len != 1 || *object.ptr != 1))
                    330:                                {
                    331:                                        goto end;
                    332:                                }
                    333:                                break;
                    334:                        default:
                    335:                                break;
                    336:                }
                    337:        }
                    338:        success = parser->success(parser);
                    339: 
                    340: end:
                    341:        parser->destroy(parser);
                    342:        return success;
                    343: }
                    344: 
                    345: /*
                    346:  * Described in header
                    347:  */
                    348: bool rsa_pss_params_build(rsa_pss_params_t *params, chunk_t *asn1)
                    349: {
                    350:        chunk_t hash = chunk_empty, mgf = chunk_empty, slen = chunk_empty;
                    351:        int alg;
                    352: 
                    353:        if (params->hash != HASH_SHA1)
                    354:        {       /* with SHA-1 we MUST omit the field */
                    355:                alg = hasher_algorithm_to_oid(params->hash);
                    356:                if (alg == OID_UNKNOWN)
                    357:                {
                    358:                        return FALSE;
                    359:                }
                    360:                hash = asn1_algorithmIdentifier(alg);
                    361:        }
                    362:        if (params->mgf1_hash != HASH_SHA1)
                    363:        {       /* with MGF1-SHA1 we MUST omit the field */
                    364:                alg = hasher_algorithm_to_oid(params->mgf1_hash);
                    365:                if (alg == OID_UNKNOWN)
                    366:                {
                    367:                        chunk_free(&hash);
                    368:                        return FALSE;
                    369:                }
                    370:                mgf = asn1_algorithmIdentifier_params(OID_MGF1,
                    371:                                                                                          asn1_algorithmIdentifier(alg));
                    372:        }
                    373:        if (params->salt_len < 0)
                    374:        {
                    375:                chunk_free(&hash);
                    376:                chunk_free(&mgf);
                    377:                return FALSE;
                    378:        }
                    379:        else if (params->salt_len != HASH_SIZE_SHA1)
                    380:        {
                    381:                slen = asn1_integer("m", asn1_integer_from_uint64(params->salt_len));
                    382:        }
                    383:        *asn1 = asn1_wrap(ASN1_SEQUENCE, "mmm",
                    384:                                hash.len ? asn1_wrap(ASN1_CONTEXT_C_0, "m", hash) : chunk_empty,
                    385:                                mgf.len ? asn1_wrap(ASN1_CONTEXT_C_1, "m", mgf) : chunk_empty,
                    386:                                slen.len ? asn1_wrap(ASN1_CONTEXT_C_2, "m", slen) : chunk_empty);
                    387:        return TRUE;
                    388: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>