Annotation of embedaddon/strongswan/src/libstrongswan/plugins/x509/x509_pkcs10.c, revision 1.1

1.1     ! misho       1: /*
        !             2:  * Copyright (C) 2005 Jan Hutter, Martin Willi
        !             3:  * Copyright (C) 2009-2017 Andreas Steffen
        !             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 "x509_pkcs10.h"
        !            18: 
        !            19: #include <library.h>
        !            20: #include <utils/debug.h>
        !            21: #include <asn1/oid.h>
        !            22: #include <asn1/asn1.h>
        !            23: #include <asn1/asn1_parser.h>
        !            24: #include <credentials/keys/private_key.h>
        !            25: #include <collections/linked_list.h>
        !            26: #include <utils/identification.h>
        !            27: 
        !            28: typedef struct private_x509_pkcs10_t private_x509_pkcs10_t;
        !            29: 
        !            30: /**
        !            31:  * Private data of a x509_pkcs10_t object.
        !            32:  */
        !            33: struct private_x509_pkcs10_t {
        !            34:        /**
        !            35:         * Public interface for this certificate.
        !            36:         */
        !            37:        x509_pkcs10_t public;
        !            38: 
        !            39:        /**
        !            40:         * PKCS#10 certificate request encoding in ASN.1 DER format
        !            41:         */
        !            42:        chunk_t encoding;
        !            43: 
        !            44:        /**
        !            45:         * PKCS#10 request body over which signature is computed
        !            46:         */
        !            47:        chunk_t certificationRequestInfo;
        !            48: 
        !            49:        /**
        !            50:         * Version of the PKCS#10 certificate request
        !            51:         */
        !            52:        u_int version;
        !            53: 
        !            54:        /**
        !            55:         * ID representing the certificate subject
        !            56:         */
        !            57:        identification_t *subject;
        !            58: 
        !            59:        /**
        !            60:         * List of subjectAltNames as identification_t
        !            61:         */
        !            62:        linked_list_t *subjectAltNames;
        !            63: 
        !            64:        /**
        !            65:         * certificate's embedded public key
        !            66:         */
        !            67:        public_key_t *public_key;
        !            68: 
        !            69:        /**
        !            70:         * challenge password
        !            71:         */
        !            72:        chunk_t challengePassword;
        !            73: 
        !            74:        /**
        !            75:         * Signature scheme
        !            76:         */
        !            77:        signature_params_t *scheme;
        !            78: 
        !            79:        /**
        !            80:         * Signature
        !            81:         */
        !            82:        chunk_t signature;
        !            83: 
        !            84:        /**
        !            85:         * Is the certificate request self-signed?
        !            86:         */
        !            87:        bool self_signed;
        !            88: 
        !            89:        /**
        !            90:         * Certificate request parsed from blob/file?
        !            91:         */
        !            92:        bool parsed;
        !            93: 
        !            94:        /**
        !            95:         * reference count
        !            96:         */
        !            97:        refcount_t ref;
        !            98: };
        !            99: 
        !           100: /**
        !           101:  * Imported from x509_cert.c
        !           102:  */
        !           103: extern bool x509_parse_generalNames(chunk_t blob, int level0, bool implicit,
        !           104:                                                                        linked_list_t *list);
        !           105: extern chunk_t x509_build_subjectAltNames(linked_list_t *list);
        !           106: 
        !           107: METHOD(certificate_t, get_type, certificate_type_t,
        !           108:        private_x509_pkcs10_t *this)
        !           109: {
        !           110:        return CERT_PKCS10_REQUEST;
        !           111: }
        !           112: 
        !           113: METHOD(certificate_t, get_subject, identification_t*,
        !           114:        private_x509_pkcs10_t *this)
        !           115: {
        !           116:        return this->subject;
        !           117: }
        !           118: 
        !           119: METHOD(certificate_t, has_subject, id_match_t,
        !           120:        private_x509_pkcs10_t *this, identification_t *subject)
        !           121: {
        !           122:        return this->subject->matches(this->subject, subject);
        !           123: }
        !           124: 
        !           125: METHOD(certificate_t, issued_by, bool,
        !           126:        private_x509_pkcs10_t *this, certificate_t *issuer,
        !           127:        signature_params_t **scheme)
        !           128: {
        !           129:        public_key_t *key;
        !           130:        bool valid;
        !           131: 
        !           132:        if (&this->public.interface.interface != issuer)
        !           133:        {
        !           134:                return FALSE;
        !           135:        }
        !           136:        if (this->self_signed)
        !           137:        {
        !           138:                valid = TRUE;
        !           139:        }
        !           140:        else
        !           141:        {
        !           142:                /* get the public key contained in the certificate request */
        !           143:                key = this->public_key;
        !           144:                if (!key)
        !           145:                {
        !           146:                        return FALSE;
        !           147:                }
        !           148:                valid = key->verify(key, this->scheme->scheme, this->scheme->params,
        !           149:                                                        this->certificationRequestInfo, this->signature);
        !           150:        }
        !           151:        if (valid && scheme)
        !           152:        {
        !           153:                *scheme = signature_params_clone(this->scheme);
        !           154:        }
        !           155:        return valid;
        !           156: }
        !           157: 
        !           158: METHOD(certificate_t, get_public_key, public_key_t*,
        !           159:        private_x509_pkcs10_t *this)
        !           160: {
        !           161:        this->public_key->get_ref(this->public_key);
        !           162:        return this->public_key;
        !           163: }
        !           164: 
        !           165: METHOD(certificate_t, get_validity, bool,
        !           166:        private_x509_pkcs10_t *this, time_t *when, time_t *not_before,
        !           167:        time_t *not_after)
        !           168: {
        !           169:        if (not_before)
        !           170:        {
        !           171:                *not_before = 0;
        !           172:        }
        !           173:        if (not_after)
        !           174:        {
        !           175:                *not_after = ~0;
        !           176:        }
        !           177:        return TRUE;
        !           178: }
        !           179: 
        !           180: METHOD(certificate_t, get_encoding, bool,
        !           181:        private_x509_pkcs10_t *this, cred_encoding_type_t type, chunk_t *encoding)
        !           182: {
        !           183:        if (type == CERT_ASN1_DER)
        !           184:        {
        !           185:                *encoding = chunk_clone(this->encoding);
        !           186:                return TRUE;
        !           187:        }
        !           188:        return lib->encoding->encode(lib->encoding, type, NULL, encoding,
        !           189:                                        CRED_PART_PKCS10_ASN1_DER, this->encoding, CRED_PART_END);
        !           190: }
        !           191: 
        !           192: METHOD(certificate_t, equals, bool,
        !           193:        private_x509_pkcs10_t *this, certificate_t *other)
        !           194: {
        !           195:        chunk_t encoding;
        !           196:        bool equal;
        !           197: 
        !           198:        if (this == (private_x509_pkcs10_t*)other)
        !           199:        {
        !           200:                return TRUE;
        !           201:        }
        !           202:        if (other->get_type(other) != CERT_PKCS10_REQUEST)
        !           203:        {
        !           204:                return FALSE;
        !           205:        }
        !           206:        if (other->equals == (void*)equals)
        !           207:        {       /* skip allocation if we have the same implementation */
        !           208:                return chunk_equals(this->encoding, ((private_x509_pkcs10_t*)other)->encoding);
        !           209:        }
        !           210:        if (!other->get_encoding(other, CERT_ASN1_DER, &encoding))
        !           211:        {
        !           212:                return FALSE;
        !           213:        }
        !           214:        equal = chunk_equals(this->encoding, encoding);
        !           215:        free(encoding.ptr);
        !           216:        return equal;
        !           217: }
        !           218: 
        !           219: METHOD(certificate_t, get_ref, certificate_t*,
        !           220:        private_x509_pkcs10_t *this)
        !           221: {
        !           222:        ref_get(&this->ref);
        !           223:        return &this->public.interface.interface;
        !           224: }
        !           225: 
        !           226: METHOD(pkcs10_t, get_challengePassword, chunk_t,
        !           227:        private_x509_pkcs10_t *this)
        !           228: {
        !           229:        return this->challengePassword;
        !           230: }
        !           231: 
        !           232: METHOD(pkcs10_t, create_subjectAltName_enumerator, enumerator_t*,
        !           233:        private_x509_pkcs10_t *this)
        !           234: {
        !           235:        return this->subjectAltNames->create_enumerator(this->subjectAltNames);
        !           236: }
        !           237: 
        !           238: /**
        !           239:  * ASN.1 definition of a PKCS#10 extension request
        !           240:  */
        !           241: static const asn1Object_t extensionRequestObjects[] = {
        !           242:        { 0, "extensions",   ASN1_SEQUENCE,     ASN1_LOOP           }, /* 0 */
        !           243:        { 1,   "extension",   ASN1_SEQUENCE,     ASN1_NONE          }, /* 1 */
        !           244:        { 2,     "extnID",        ASN1_OID,          ASN1_BODY          }, /* 2 */
        !           245:        { 2,     "critical",  ASN1_BOOLEAN,      ASN1_DEF|ASN1_BODY }, /* 3 */
        !           246:        { 2,     "extnValue", ASN1_OCTET_STRING, ASN1_BODY          }, /* 4 */
        !           247:        { 1, "end loop",      ASN1_EOC,          ASN1_END                       }, /* 5 */
        !           248:        { 0, "exit",          ASN1_EOC,          ASN1_EXIT          }
        !           249: };
        !           250: #define PKCS10_EXTN_ID                 2
        !           251: #define PKCS10_EXTN_CRITICAL   3
        !           252: #define PKCS10_EXTN_VALUE              4
        !           253: 
        !           254: /**
        !           255:  * Parses a PKCS#10 extension request
        !           256:  */
        !           257: static bool parse_extension_request(private_x509_pkcs10_t *this, chunk_t blob, int level0)
        !           258: {
        !           259:        asn1_parser_t *parser;
        !           260:        chunk_t object;
        !           261:        int objectID;
        !           262:        int extn_oid = OID_UNKNOWN;
        !           263:        bool success = FALSE;
        !           264:        bool critical;
        !           265: 
        !           266:        parser = asn1_parser_create(extensionRequestObjects, blob);
        !           267:        parser->set_top_level(parser, level0);
        !           268: 
        !           269:        while (parser->iterate(parser, &objectID, &object))
        !           270:        {
        !           271:                u_int level = parser->get_level(parser)+1;
        !           272: 
        !           273:                switch (objectID)
        !           274:                {
        !           275:                        case PKCS10_EXTN_ID:
        !           276:                                extn_oid = asn1_known_oid(object);
        !           277:                                break;
        !           278:                        case PKCS10_EXTN_CRITICAL:
        !           279:                                critical = object.len && *object.ptr;
        !           280:                                DBG2(DBG_ASN, "  %s", critical ? "TRUE" : "FALSE");
        !           281:                                break;
        !           282:                        case PKCS10_EXTN_VALUE:
        !           283:                        {
        !           284:                                switch (extn_oid)
        !           285:                                {
        !           286:                                        case OID_SUBJECT_ALT_NAME:
        !           287:                                                if (!x509_parse_generalNames(object, level, FALSE,
        !           288:                                                                                                         this->subjectAltNames))
        !           289:                                                {
        !           290:                                                        goto end;
        !           291:                                                }
        !           292:                                                break;
        !           293:                                        default:
        !           294:                                                break;
        !           295:                                }
        !           296:                                break;
        !           297:                        }
        !           298:                        default:
        !           299:                                break;
        !           300:                }
        !           301:        }
        !           302:        success = parser->success(parser);
        !           303: 
        !           304: end:
        !           305:        parser->destroy(parser);
        !           306: 
        !           307:        return success;
        !           308: }
        !           309: 
        !           310: /**
        !           311:  * Parses a PKCS#10 challenge password
        !           312:  */
        !           313: static bool parse_challengePassword(private_x509_pkcs10_t *this, chunk_t blob, int level)
        !           314: {
        !           315:        char tag;
        !           316: 
        !           317:        if (blob.len < 2)
        !           318:        {
        !           319:                DBG1(DBG_ASN, "L%d - challengePassword:  ASN.1 object smaller "
        !           320:                         "than 2 octets", level);
        !           321:                return FALSE;
        !           322:        }
        !           323:        tag = *blob.ptr;
        !           324:        if (tag < ASN1_UTF8STRING || tag > ASN1_IA5STRING)
        !           325:        {
        !           326:                DBG1(DBG_ASN, "L%d - challengePassword:  ASN.1 object is not "
        !           327:                         "a character string", level);
        !           328:                return FALSE;
        !           329:        }
        !           330:        if (asn1_length(&blob) == ASN1_INVALID_LENGTH)
        !           331:        {
        !           332:                DBG1(DBG_ASN, "L%d - challengePassword:  ASN.1 object has an "
        !           333:                         "invalid length", level);
        !           334:                return FALSE;
        !           335:        }
        !           336:        DBG2(DBG_ASN, "L%d - challengePassword:", level);
        !           337:        DBG4(DBG_ASN, "  '%.*s'", (int)blob.len, blob.ptr);
        !           338:        return TRUE;
        !           339: }
        !           340: 
        !           341: /**
        !           342:  * ASN.1 definition of a PKCS#10 certificate request
        !           343:  */
        !           344: static const asn1Object_t certificationRequestObjects[] = {
        !           345:        { 0, "certificationRequest",       ASN1_SEQUENCE,    ASN1_OBJ  }, /*  0 */
        !           346:        { 1,   "certificationRequestInfo", ASN1_SEQUENCE,    ASN1_OBJ  }, /*  1 */
        !           347:        { 2,     "version",                ASN1_INTEGER,     ASN1_BODY }, /*  2 */
        !           348:        { 2,     "subject",                ASN1_SEQUENCE,    ASN1_OBJ  }, /*  3 */
        !           349:        { 2,     "subjectPublicKeyInfo",   ASN1_SEQUENCE,    ASN1_RAW  }, /*  4 */
        !           350:        { 2,     "attributes",             ASN1_CONTEXT_C_0, ASN1_LOOP }, /*  5 */
        !           351:        { 3,       "attribute",            ASN1_SEQUENCE,    ASN1_NONE }, /*  6 */
        !           352:        { 4,         "type",               ASN1_OID,         ASN1_BODY }, /*  7 */
        !           353:        { 4,         "values",             ASN1_SET,         ASN1_LOOP }, /*  8 */
        !           354:        { 5,           "value",            ASN1_EOC,         ASN1_RAW  }, /*  9 */
        !           355:        { 4,         "end loop",           ASN1_EOC,         ASN1_END  }, /* 10 */
        !           356:        { 2,     "end loop",               ASN1_EOC,         ASN1_END  }, /* 11 */
        !           357:        { 1,   "signatureAlgorithm",       ASN1_EOC,         ASN1_RAW  }, /* 12 */
        !           358:        { 1,    "signature",               ASN1_BIT_STRING,  ASN1_BODY }, /* 13 */
        !           359:        { 0, "exit",                       ASN1_EOC,         ASN1_EXIT }
        !           360: };
        !           361: #define PKCS10_CERT_REQUEST_INFO                1
        !           362: #define PKCS10_VERSION                                  2
        !           363: #define PKCS10_SUBJECT                                  3
        !           364: #define PKCS10_SUBJECT_PUBLIC_KEY_INFO  4
        !           365: #define PKCS10_ATTR_TYPE                                7
        !           366: #define PKCS10_ATTR_VALUE                               9
        !           367: #define PKCS10_ALGORITHM                               12
        !           368: #define PKCS10_SIGNATURE                               13
        !           369: 
        !           370: /**
        !           371:  * Parses a PKCS#10 certificate request
        !           372:  */
        !           373: static bool parse_certificate_request(private_x509_pkcs10_t *this)
        !           374: {
        !           375:        asn1_parser_t *parser;
        !           376:        chunk_t object;
        !           377:        int objectID;
        !           378:        int attr_oid = OID_UNKNOWN;
        !           379:        bool success = FALSE;
        !           380: 
        !           381:        parser = asn1_parser_create(certificationRequestObjects, this->encoding);
        !           382: 
        !           383:        while (parser->iterate(parser, &objectID, &object))
        !           384:        {
        !           385:                u_int level = parser->get_level(parser)+1;
        !           386: 
        !           387:                switch (objectID)
        !           388:                {
        !           389:                        case PKCS10_CERT_REQUEST_INFO:
        !           390:                                this->certificationRequestInfo = object;
        !           391:                                break;
        !           392:                        case PKCS10_VERSION:
        !           393:                                if (object.len > 0 && *object.ptr != 0)
        !           394:                                {
        !           395:                                        DBG1(DBG_ASN, "PKCS#10 certificate request format is "
        !           396:                                                 "not version 1");
        !           397:                                        goto end;
        !           398:                                }
        !           399:                                break;
        !           400:                        case PKCS10_SUBJECT:
        !           401:                                this->subject = identification_create_from_encoding(ID_DER_ASN1_DN, object);
        !           402:                                DBG2(DBG_ASN, "  '%Y'", this->subject);
        !           403:                                break;
        !           404:                        case PKCS10_SUBJECT_PUBLIC_KEY_INFO:
        !           405:                                this->public_key = lib->creds->create(lib->creds, CRED_PUBLIC_KEY,
        !           406:                                                KEY_ANY, BUILD_BLOB_ASN1_DER, object, BUILD_END);
        !           407:                                if (!this->public_key)
        !           408:                                {
        !           409:                                        goto end;
        !           410:                                }
        !           411:                                break;
        !           412:                        case PKCS10_ATTR_TYPE:
        !           413:                                attr_oid = asn1_known_oid(object);
        !           414:                                break;
        !           415:                        case PKCS10_ATTR_VALUE:
        !           416:                                switch (attr_oid)
        !           417:                                {
        !           418:                                        case OID_EXTENSION_REQUEST:
        !           419:                                                if (!parse_extension_request(this, object, level))
        !           420:                                                {
        !           421:                                                        goto end;
        !           422:                                                }
        !           423:                                                break;
        !           424:                                        case OID_CHALLENGE_PASSWORD:
        !           425:                                                if (!parse_challengePassword(this, object, level))
        !           426:                                                {
        !           427:                                                        goto end;
        !           428:                                                }
        !           429:                                                break;
        !           430:                                        default:
        !           431:                                                break;
        !           432:                                }
        !           433:                                break;
        !           434:                        case PKCS10_ALGORITHM:
        !           435:                                INIT(this->scheme);
        !           436:                                if (!signature_params_parse(object, level, this->scheme))
        !           437:                                {
        !           438:                                        DBG1(DBG_ASN, "  unable to parse signature algorithm");
        !           439:                                        goto end;
        !           440:                                }
        !           441:                                break;
        !           442:                        case PKCS10_SIGNATURE:
        !           443:                                this->signature = chunk_skip(object, 1);
        !           444:                                break;
        !           445:                        default:
        !           446:                                break;
        !           447:                }
        !           448:        }
        !           449:        success = parser->success(parser);
        !           450: 
        !           451: end:
        !           452:        parser->destroy(parser);
        !           453:        if (success)
        !           454:        {
        !           455:                /* check if the certificate request is self-signed */
        !           456:                if (issued_by(this, &this->public.interface.interface, NULL))
        !           457:                {
        !           458:                        this->self_signed = TRUE;
        !           459:                }
        !           460:                else
        !           461:                {
        !           462:                        DBG1(DBG_LIB, "certificate request is not self-signed");
        !           463:                        success = FALSE;
        !           464:                }
        !           465:        }
        !           466:        return success;
        !           467: }
        !           468: 
        !           469: METHOD(certificate_t, destroy, void,
        !           470:        private_x509_pkcs10_t *this)
        !           471: {
        !           472:        if (ref_put(&this->ref))
        !           473:        {
        !           474:                this->subjectAltNames->destroy_offset(this->subjectAltNames,
        !           475:                                                                        offsetof(identification_t, destroy));
        !           476:                signature_params_destroy(this->scheme);
        !           477:                DESTROY_IF(this->subject);
        !           478:                DESTROY_IF(this->public_key);
        !           479:                chunk_free(&this->encoding);
        !           480:                if (!this->parsed)
        !           481:                {       /* only parsed certificate requests point these fields to "encoded" */
        !           482:                        chunk_free(&this->certificationRequestInfo);
        !           483:                        chunk_free(&this->challengePassword);
        !           484:                        chunk_free(&this->signature);
        !           485:                }
        !           486:                free(this);
        !           487:        }
        !           488: }
        !           489: 
        !           490: /**
        !           491:  * create an empty but initialized PKCS#10 certificate request
        !           492:  */
        !           493: static private_x509_pkcs10_t* create_empty(void)
        !           494: {
        !           495:        private_x509_pkcs10_t *this;
        !           496: 
        !           497:        INIT(this,
        !           498:                .public = {
        !           499:                        .interface = {
        !           500:                                .interface = {
        !           501:                                        .get_type = _get_type,
        !           502:                                        .get_subject = _get_subject,
        !           503:                                        .get_issuer = _get_subject,
        !           504:                                        .has_subject = _has_subject,
        !           505:                                        .has_issuer = _has_subject,
        !           506:                                        .issued_by = _issued_by,
        !           507:                                        .get_public_key = _get_public_key,
        !           508:                                        .get_validity = _get_validity,
        !           509:                                        .get_encoding = _get_encoding,
        !           510:                                        .equals = _equals,
        !           511:                                        .get_ref = _get_ref,
        !           512:                                        .destroy = _destroy,
        !           513:                                },
        !           514:                                .get_challengePassword = _get_challengePassword,
        !           515:                                .create_subjectAltName_enumerator = _create_subjectAltName_enumerator,
        !           516:                        },
        !           517:                },
        !           518:                .subjectAltNames = linked_list_create(),
        !           519:                .ref = 1,
        !           520:        );
        !           521: 
        !           522:        return this;
        !           523: }
        !           524: 
        !           525: /**
        !           526:  * Generate and sign a new certificate request
        !           527:  */
        !           528: static bool generate(private_x509_pkcs10_t *cert, private_key_t *sign_key,
        !           529:                                         int digest_alg)
        !           530: {
        !           531:        chunk_t key_info, subjectAltNames, attributes;
        !           532:        chunk_t extensionRequest  = chunk_empty;
        !           533:        chunk_t challengePassword = chunk_empty, sig_scheme = chunk_empty;
        !           534:        identification_t *subject;
        !           535: 
        !           536:        subject = cert->subject;
        !           537:        cert->public_key = sign_key->get_public_key(sign_key);
        !           538: 
        !           539:        /* select signature scheme, if not already specified */
        !           540:        if (!cert->scheme)
        !           541:        {
        !           542:                INIT(cert->scheme,
        !           543:                        .scheme = signature_scheme_from_oid(
        !           544:                                                                hasher_signature_algorithm_to_oid(digest_alg,
        !           545:                                                                                                sign_key->get_type(sign_key))),
        !           546:                );
        !           547:        }
        !           548:        if (cert->scheme->scheme == SIGN_UNKNOWN)
        !           549:        {
        !           550:                return FALSE;
        !           551:        }
        !           552:        if (!signature_params_build(cert->scheme, &sig_scheme))
        !           553:        {
        !           554:                return FALSE;
        !           555:        }
        !           556: 
        !           557:        if (!cert->public_key->get_encoding(cert->public_key,
        !           558:                                                                                PUBKEY_SPKI_ASN1_DER, &key_info))
        !           559:        {
        !           560:                chunk_free(&sig_scheme);
        !           561:                return FALSE;
        !           562:        }
        !           563: 
        !           564:        /* encode subjectAltNames */
        !           565:        subjectAltNames = x509_build_subjectAltNames(cert->subjectAltNames);
        !           566: 
        !           567:        if (subjectAltNames.ptr)
        !           568:        {
        !           569:                extensionRequest = asn1_wrap(ASN1_SEQUENCE, "mm",
        !           570:                                        asn1_build_known_oid(OID_EXTENSION_REQUEST),
        !           571:                                        asn1_wrap(ASN1_SET, "m",
        !           572:                                                asn1_wrap(ASN1_SEQUENCE, "m", subjectAltNames)
        !           573:                                        ));
        !           574:        }
        !           575:        if (cert->challengePassword.len > 0)
        !           576:        {
        !           577:                asn1_t type = asn1_is_printablestring(cert->challengePassword) ?
        !           578:                                                                ASN1_PRINTABLESTRING : ASN1_T61STRING;
        !           579: 
        !           580:                challengePassword = asn1_wrap(ASN1_SEQUENCE, "mm",
        !           581:                                        asn1_build_known_oid(OID_CHALLENGE_PASSWORD),
        !           582:                                        asn1_wrap(ASN1_SET, "m",
        !           583:                                                asn1_simple_object(type, cert->challengePassword)
        !           584:                                        )
        !           585:                        );
        !           586:        }
        !           587:        attributes = asn1_wrap(ASN1_CONTEXT_C_0, "mm", extensionRequest,
        !           588:                                                                                                   challengePassword);
        !           589: 
        !           590:        cert->certificationRequestInfo = asn1_wrap(ASN1_SEQUENCE, "ccmm",
        !           591:                                                        ASN1_INTEGER_0,
        !           592:                                                        subject->get_encoding(subject),
        !           593:                                                        key_info,
        !           594:                                                        attributes);
        !           595: 
        !           596:        if (!sign_key->sign(sign_key, cert->scheme->scheme, cert->scheme->params,
        !           597:                                                cert->certificationRequestInfo, &cert->signature))
        !           598:        {
        !           599:                chunk_free(&sig_scheme);
        !           600:                return FALSE;
        !           601:        }
        !           602: 
        !           603:        cert->encoding = asn1_wrap(ASN1_SEQUENCE, "cmm",
        !           604:                                                           cert->certificationRequestInfo,
        !           605:                                                           sig_scheme,
        !           606:                                                           asn1_bitstring("c", cert->signature));
        !           607:        return TRUE;
        !           608: }
        !           609: 
        !           610: /**
        !           611:  * See header.
        !           612:  */
        !           613: x509_pkcs10_t *x509_pkcs10_load(certificate_type_t type, va_list args)
        !           614: {
        !           615:        chunk_t blob = chunk_empty;
        !           616: 
        !           617:        while (TRUE)
        !           618:        {
        !           619:                switch (va_arg(args, builder_part_t))
        !           620:                {
        !           621:                        case BUILD_BLOB_ASN1_DER:
        !           622:                                blob = va_arg(args, chunk_t);
        !           623:                                continue;
        !           624:                        case BUILD_END:
        !           625:                                break;
        !           626:                        default:
        !           627:                                return NULL;
        !           628:                }
        !           629:                break;
        !           630:        }
        !           631: 
        !           632:        if (blob.ptr)
        !           633:        {
        !           634:                private_x509_pkcs10_t *cert = create_empty();
        !           635: 
        !           636:                cert->encoding = chunk_clone(blob);
        !           637:                cert->parsed = TRUE;
        !           638:                if (parse_certificate_request(cert))
        !           639:                {
        !           640:                        return &cert->public;
        !           641:                }
        !           642:                destroy(cert);
        !           643:        }
        !           644:        return NULL;
        !           645: }
        !           646: 
        !           647: /**
        !           648:  * See header.
        !           649:  */
        !           650: x509_pkcs10_t *x509_pkcs10_gen(certificate_type_t type, va_list args)
        !           651: {
        !           652:        private_x509_pkcs10_t *cert;
        !           653:        private_key_t *sign_key = NULL;
        !           654:        hash_algorithm_t digest_alg = HASH_SHA1;
        !           655: 
        !           656:        cert = create_empty();
        !           657:        while (TRUE)
        !           658:        {
        !           659:                switch (va_arg(args, builder_part_t))
        !           660:                {
        !           661:                        case BUILD_SIGNING_KEY:
        !           662:                                sign_key = va_arg(args, private_key_t*);
        !           663:                                continue;
        !           664:                        case BUILD_SUBJECT:
        !           665:                                cert->subject = va_arg(args, identification_t*);
        !           666:                                cert->subject = cert->subject->clone(cert->subject);
        !           667:                                continue;
        !           668:                        case BUILD_SUBJECT_ALTNAMES:
        !           669:                        {
        !           670:                                enumerator_t *enumerator;
        !           671:                                identification_t *id;
        !           672:                                linked_list_t *list;
        !           673: 
        !           674:                                list = va_arg(args, linked_list_t*);
        !           675:                                enumerator = list->create_enumerator(list);
        !           676:                                while (enumerator->enumerate(enumerator, &id))
        !           677:                                {
        !           678:                                        cert->subjectAltNames->insert_last(cert->subjectAltNames,
        !           679:                                                                                                           id->clone(id));
        !           680:                                }
        !           681:                                enumerator->destroy(enumerator);
        !           682:                                continue;
        !           683:                        }
        !           684:                        case BUILD_CHALLENGE_PWD:
        !           685:                                cert->challengePassword = chunk_clone(va_arg(args, chunk_t));
        !           686:                                continue;
        !           687:                        case BUILD_SIGNATURE_SCHEME:
        !           688:                                cert->scheme = va_arg(args, signature_params_t*);
        !           689:                                cert->scheme = signature_params_clone(cert->scheme);
        !           690:                                continue;
        !           691:                        case BUILD_DIGEST_ALG:
        !           692:                                digest_alg = va_arg(args, int);
        !           693:                                continue;
        !           694:                        case BUILD_END:
        !           695:                                break;
        !           696:                        default:
        !           697:                                destroy(cert);
        !           698:                                return NULL;
        !           699:                }
        !           700:                break;
        !           701:        }
        !           702: 
        !           703:        if (sign_key && generate(cert, sign_key, digest_alg))
        !           704:        {
        !           705:                return &cert->public;
        !           706:        }
        !           707:        destroy(cert);
        !           708:        return NULL;
        !           709: }
        !           710: 

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