Annotation of embedaddon/strongswan/src/libstrongswan/credentials/keys/signature_params.c, revision 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>