Annotation of embedaddon/strongswan/src/libstrongswan/plugins/x509/x509_ocsp_request.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2017-2019 Tobias Brunner
                      3:  * Copyright (C) 2008-2009 Martin Willi
                      4:  * Copyright (C) 2007-2014 Andreas Steffen
                      5:  * HSR Hochschule fuer Technik Rapperswil
                      6:  * Copyright (C) 2003 Christoph Gysin, Simon Zwahlen
                      7:  *
                      8:  * This program is free software; you can redistribute it and/or modify it
                      9:  * under the terms of the GNU General Public License as published by the
                     10:  * Free Software Foundation; either version 2 of the License, or (at your
                     11:  * option) any later version.  See <http://www.fsf.org/copyleft/gpl.txt>.
                     12:  *
                     13:  * This program is distributed in the hope that it will be useful, but
                     14:  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
                     15:  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
                     16:  * for more details.
                     17:  */
                     18: 
                     19: #include "x509_ocsp_request.h"
                     20: 
                     21: #include <library.h>
                     22: #include <asn1/oid.h>
                     23: #include <asn1/asn1.h>
                     24: #include <utils/identification.h>
                     25: #include <collections/linked_list.h>
                     26: #include <utils/debug.h>
                     27: #include <credentials/certificates/x509.h>
                     28: #include <credentials/keys/private_key.h>
                     29: 
                     30: #define NONCE_LEN              16
                     31: 
                     32: typedef struct private_x509_ocsp_request_t private_x509_ocsp_request_t;
                     33: 
                     34: /**
                     35:  * private data of x509_ocsp_request
                     36:  */
                     37: struct private_x509_ocsp_request_t {
                     38: 
                     39:        /**
                     40:         * public functions
                     41:         */
                     42:        x509_ocsp_request_t public;
                     43: 
                     44:        /**
                     45:         * CA the candidates belong to
                     46:         */
                     47:        x509_t *ca;
                     48: 
                     49:        /**
                     50:         * Requestor name, subject of cert used if not set
                     51:         */
                     52:        identification_t *requestor;
                     53: 
                     54:        /**
                     55:         * Requestor certificate, included in request
                     56:         */
                     57:        certificate_t *cert;
                     58: 
                     59:        /**
                     60:         * Requestor private key to sign request
                     61:         */
                     62:        private_key_t *key;
                     63: 
                     64:        /**
                     65:         * list of certificates to check, x509_t
                     66:         */
                     67:        linked_list_t *candidates;
                     68: 
                     69:        /**
                     70:         * nonce used in request
                     71:         */
                     72:        chunk_t nonce;
                     73: 
                     74:        /**
                     75:         * encoded OCSP request
                     76:         */
                     77:        chunk_t encoding;
                     78: 
                     79:        /**
                     80:         * reference count
                     81:         */
                     82:        refcount_t ref;
                     83: };
                     84: 
                     85: static const chunk_t ASN1_nonce_oid = chunk_from_chars(
                     86:        0x06, 0x09,
                     87:                  0x2B, 0x06,
                     88:                                0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x02
                     89: );
                     90: static const chunk_t ASN1_response_oid = chunk_from_chars(
                     91:        0x06, 0x09,
                     92:                  0x2B, 0x06,
                     93:                                0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x04
                     94: );
                     95: static const chunk_t ASN1_response_content = chunk_from_chars(
                     96:        0x04, 0x0D,
                     97:                  0x30, 0x0B,
                     98:                                0x06, 0x09,
                     99:                                0x2B, 0x06,
                    100:                                0x01, 0x05, 0x05, 0x07, 0x30, 0x01, 0x01
                    101: );
                    102: 
                    103: /**
                    104:  * build requestorName
                    105:  */
                    106: static chunk_t build_requestorName(private_x509_ocsp_request_t *this)
                    107: {
                    108:        if (this->requestor || this->cert)
                    109:        {       /* use requestor name, fallback to his cert subject */
                    110:                if (!this->requestor)
                    111:                {
                    112:                        this->requestor = this->cert->get_subject(this->cert);
                    113:                        this->requestor = this->requestor->clone(this->requestor);
                    114:                }
                    115:                return asn1_wrap(ASN1_CONTEXT_C_1, "m",
                    116:                                        asn1_simple_object(ASN1_CONTEXT_C_4,
                    117:                                                this->requestor->get_encoding(this->requestor)));
                    118: 
                    119:        }
                    120:        return chunk_empty;
                    121: }
                    122: 
                    123: /**
                    124:  * build Request, not using singleRequestExtensions
                    125:  */
                    126: static chunk_t build_Request(private_x509_ocsp_request_t *this,
                    127:                                                         chunk_t issuerNameHash, chunk_t issuerKeyHash,
                    128:                                                         chunk_t serialNumber)
                    129: {
                    130:        return asn1_wrap(ASN1_SEQUENCE, "m",
                    131:                                asn1_wrap(ASN1_SEQUENCE, "mmmm",
                    132:                                        asn1_algorithmIdentifier(OID_SHA1),
                    133:                                        asn1_simple_object(ASN1_OCTET_STRING, issuerNameHash),
                    134:                                        asn1_simple_object(ASN1_OCTET_STRING, issuerKeyHash),
                    135:                                        asn1_simple_object(ASN1_INTEGER, serialNumber)));
                    136: }
                    137: 
                    138: /**
                    139:  * build requestList
                    140:  */
                    141: static chunk_t build_requestList(private_x509_ocsp_request_t *this)
                    142: {
                    143:        chunk_t issuerNameHash, issuerKeyHash;
                    144:        identification_t *issuer;
                    145:        x509_t *x509;
                    146:        certificate_t *cert;
                    147:        chunk_t list = chunk_empty;
                    148:        public_key_t *public;
                    149: 
                    150:        cert = (certificate_t*)this->ca;
                    151:        public = cert->get_public_key(cert);
                    152:        if (public)
                    153:        {
                    154:                hasher_t *hasher = lib->crypto->create_hasher(lib->crypto, HASH_SHA1);
                    155:                if (hasher)
                    156:                {
                    157:                        if (public->get_fingerprint(public, KEYID_PUBKEY_SHA1,
                    158:                                                                                &issuerKeyHash))
                    159:                        {
                    160:                                enumerator_t *enumerator;
                    161: 
                    162:                                issuer = cert->get_subject(cert);
                    163:                                if (hasher->allocate_hash(hasher, issuer->get_encoding(issuer),
                    164:                                                                                  &issuerNameHash))
                    165:                                {
                    166:                                        enumerator = this->candidates->create_enumerator(
                    167:                                                                                                                        this->candidates);
                    168:                                        while (enumerator->enumerate(enumerator, &x509))
                    169:                                        {
                    170:                                                chunk_t request, serialNumber;
                    171: 
                    172:                                                serialNumber = x509->get_serial(x509);
                    173:                                                request = build_Request(this, issuerNameHash,
                    174:                                                                                                issuerKeyHash, serialNumber);
                    175:                                                list = chunk_cat("mm", list, request);
                    176:                                        }
                    177:                                        enumerator->destroy(enumerator);
                    178:                                        chunk_free(&issuerNameHash);
                    179:                                }
                    180:                                hasher->destroy(hasher);
                    181:                        }
                    182:                }
                    183:                else
                    184:                {
                    185:                        DBG1(DBG_LIB, "creating OCSP request failed, SHA1 not supported");
                    186:                }
                    187:                public->destroy(public);
                    188:        }
                    189:        else
                    190:        {
                    191:                DBG1(DBG_LIB, "creating OCSP request failed, CA certificate has "
                    192:                         "no public key");
                    193:        }
                    194:        return asn1_wrap(ASN1_SEQUENCE, "m", list);
                    195: }
                    196: 
                    197: /**
                    198:  * build nonce extension
                    199:  */
                    200: static chunk_t build_nonce(private_x509_ocsp_request_t *this)
                    201: {
                    202:        rng_t *rng;
                    203: 
                    204:        rng = lib->crypto->create_rng(lib->crypto, RNG_WEAK);
                    205:        if (!rng || !rng->allocate_bytes(rng, NONCE_LEN, &this->nonce))
                    206:        {
                    207:                DBG1(DBG_LIB, "creating OCSP request nonce failed, no RNG found");
                    208:                DESTROY_IF(rng);
                    209:                return chunk_empty;
                    210:        }
                    211:        rng->destroy(rng);
                    212:        return asn1_wrap(ASN1_SEQUENCE, "cm", ASN1_nonce_oid,
                    213:                                asn1_wrap(ASN1_OCTET_STRING, "m",
                    214:                                        asn1_simple_object(ASN1_OCTET_STRING, this->nonce)));
                    215: }
                    216: 
                    217: /**
                    218:  * build acceptableResponses extension
                    219:  */
                    220: static chunk_t build_acceptableResponses(private_x509_ocsp_request_t *this)
                    221: {
                    222:        return asn1_wrap(ASN1_SEQUENCE, "cc",
                    223:                                ASN1_response_oid,
                    224:                                ASN1_response_content);
                    225: }
                    226: 
                    227: /**
                    228:  * build requestExtensions
                    229:  */
                    230: static chunk_t build_requestExtensions(private_x509_ocsp_request_t *this)
                    231: {
                    232:        return asn1_wrap(ASN1_CONTEXT_C_2, "m",
                    233:                                asn1_wrap(ASN1_SEQUENCE, "mm",
                    234:                                        build_nonce(this),
                    235:                                        build_acceptableResponses(this)));
                    236: }
                    237: 
                    238: /**
                    239:  * build tbsRequest
                    240:  */
                    241: static chunk_t build_tbsRequest(private_x509_ocsp_request_t *this)
                    242: {
                    243:        return asn1_wrap(ASN1_SEQUENCE, "mmm",
                    244:                                build_requestorName(this),
                    245:                                build_requestList(this),
                    246:                                build_requestExtensions(this));
                    247: }
                    248: 
                    249: /**
                    250:  * Build the optionalSignature
                    251:  */
                    252: static chunk_t build_optionalSignature(private_x509_ocsp_request_t *this,
                    253:                                                                           chunk_t tbsRequest)
                    254: {
                    255:        int oid;
                    256:        signature_scheme_t scheme;
                    257:        chunk_t certs = chunk_empty, signature, encoding;
                    258: 
                    259:        switch (this->key->get_type(this->key))
                    260:        {
                    261:                /* TODO: use a generic mapping function */
                    262:                case KEY_RSA:
                    263:                        oid = OID_SHA1_WITH_RSA;
                    264:                        scheme = SIGN_RSA_EMSA_PKCS1_SHA1;
                    265:                        break;
                    266:                case KEY_ECDSA:
                    267:                        oid = OID_ECDSA_WITH_SHA1;
                    268:                        scheme = SIGN_ECDSA_WITH_SHA1_DER;
                    269:                        break;
                    270:                case KEY_BLISS:
                    271:                        oid = OID_BLISS_WITH_SHA2_512;
                    272:                        scheme = SIGN_BLISS_WITH_SHA2_512;
                    273:                        break;
                    274:                default:
                    275:                        DBG1(DBG_LIB, "unable to sign OCSP request, %N signature not "
                    276:                                 "supported", key_type_names, this->key->get_type(this->key));
                    277:                        return chunk_empty;
                    278:        }
                    279: 
                    280:        if (!this->key->sign(this->key, scheme, NULL, tbsRequest, &signature))
                    281:        {
                    282:                DBG1(DBG_LIB, "creating OCSP signature failed, skipped");
                    283:                return chunk_empty;
                    284:        }
                    285:        if (this->cert &&
                    286:                this->cert->get_encoding(this->cert, CERT_ASN1_DER, &encoding))
                    287:        {
                    288:                certs = asn1_wrap(ASN1_CONTEXT_C_0, "m",
                    289:                                        asn1_wrap(ASN1_SEQUENCE, "m", encoding));
                    290:        }
                    291:        return asn1_wrap(ASN1_CONTEXT_C_0, "m",
                    292:                                asn1_wrap(ASN1_SEQUENCE, "cmm",
                    293:                                        asn1_algorithmIdentifier(oid),
                    294:                                        asn1_bitstring("m", signature),
                    295:                                        certs));
                    296: }
                    297: 
                    298: /**
                    299:  * Build the OCSPRequest data
                    300:  *
                    301:  */
                    302: static chunk_t build_OCSPRequest(private_x509_ocsp_request_t *this)
                    303: {
                    304:        chunk_t tbsRequest, optionalSignature = chunk_empty;
                    305: 
                    306:        tbsRequest = build_tbsRequest(this);
                    307:        if (this->key)
                    308:        {
                    309:                optionalSignature = build_optionalSignature(this, tbsRequest);
                    310:        }
                    311:        return asn1_wrap(ASN1_SEQUENCE, "mm", tbsRequest, optionalSignature);
                    312: }
                    313: 
                    314: 
                    315: METHOD(certificate_t, get_type, certificate_type_t,
                    316:        private_x509_ocsp_request_t *this)
                    317: {
                    318:        return CERT_X509_OCSP_REQUEST;
                    319: }
                    320: 
                    321: METHOD(certificate_t, get_subject, identification_t*,
                    322:        private_x509_ocsp_request_t *this)
                    323: {
                    324:        certificate_t *ca = (certificate_t*)this->ca;
                    325: 
                    326:        if (this->requestor)
                    327:        {
                    328:                return this->requestor;
                    329:        }
                    330:        if (this->cert)
                    331:        {
                    332:                return this->cert->get_subject(this->cert);
                    333:        }
                    334:        return ca->get_subject(ca);
                    335: }
                    336: 
                    337: METHOD(certificate_t, get_issuer, identification_t*,
                    338:        private_x509_ocsp_request_t *this)
                    339: {
                    340:        certificate_t *ca = (certificate_t*)this->ca;
                    341: 
                    342:        return ca->get_subject(ca);
                    343: }
                    344: 
                    345: METHOD(certificate_t, has_subject, id_match_t,
                    346:        private_x509_ocsp_request_t *this, identification_t *subject)
                    347: {
                    348:        certificate_t *current;
                    349:        enumerator_t *enumerator;
                    350:        id_match_t match, best = ID_MATCH_NONE;
                    351: 
                    352:        enumerator = this->candidates->create_enumerator(this->candidates);
                    353:        while (enumerator->enumerate(enumerator, &current))
                    354:        {
                    355:                match = current->has_subject(current, subject);
                    356:                if (match > best)
                    357:                {
                    358:                        best = match;
                    359:                }
                    360:        }
                    361:        enumerator->destroy(enumerator);
                    362:        return best;
                    363: }
                    364: 
                    365: METHOD(certificate_t, has_issuer, id_match_t,
                    366:        private_x509_ocsp_request_t *this,
                    367:                                                         identification_t *issuer)
                    368: {
                    369:        certificate_t *ca = (certificate_t*)this->ca;
                    370: 
                    371:        return ca->has_subject(ca, issuer);
                    372: }
                    373: 
                    374: METHOD(certificate_t, issued_by, bool,
                    375:        private_x509_ocsp_request_t *this, certificate_t *issuer,
                    376:        signature_params_t **scheme)
                    377: {
                    378:        DBG1(DBG_LIB, "OCSP request validation not implemented!");
                    379:        return FALSE;
                    380: }
                    381: 
                    382: METHOD(certificate_t, get_public_key, public_key_t*,
                    383:        private_x509_ocsp_request_t *this)
                    384: {
                    385:        return NULL;
                    386: }
                    387: 
                    388: METHOD(certificate_t, get_validity, bool,
                    389:        private_x509_ocsp_request_t *this, time_t *when, time_t *not_before,
                    390:        time_t *not_after)
                    391: {
                    392:        certificate_t *cert;
                    393: 
                    394:        if (this->cert)
                    395:        {
                    396:                cert = this->cert;
                    397:        }
                    398:        else
                    399:        {
                    400:                cert = (certificate_t*)this->ca;
                    401:        }
                    402:        return cert->get_validity(cert, when, not_before, not_after);
                    403: }
                    404: 
                    405: METHOD(certificate_t, get_encoding, bool,
                    406:        private_x509_ocsp_request_t *this, cred_encoding_type_t type,
                    407:        chunk_t *encoding)
                    408: {
                    409:        if (type == CERT_ASN1_DER)
                    410:        {
                    411:                *encoding = chunk_clone(this->encoding);
                    412:                return TRUE;
                    413:        }
                    414:        return lib->encoding->encode(lib->encoding, type, NULL, encoding,
                    415:                                CRED_PART_X509_OCSP_REQ_ASN1_DER, this->encoding, CRED_PART_END);
                    416: }
                    417: 
                    418: METHOD(certificate_t, equals, bool,
                    419:        private_x509_ocsp_request_t *this, certificate_t *other)
                    420: {
                    421:        chunk_t encoding;
                    422:        bool equal;
                    423: 
                    424:        if (this == (private_x509_ocsp_request_t*)other)
                    425:        {
                    426:                return TRUE;
                    427:        }
                    428:        if (other->get_type(other) != CERT_X509_OCSP_REQUEST)
                    429:        {
                    430:                return FALSE;
                    431:        }
                    432:        if (other->equals == (void*)equals)
                    433:        {       /* skip allocation if we have the same implementation */
                    434:                return chunk_equals(this->encoding, ((private_x509_ocsp_request_t*)other)->encoding);
                    435:        }
                    436:        if (!other->get_encoding(other, CERT_ASN1_DER, &encoding))
                    437:        {
                    438:                return FALSE;
                    439:        }
                    440:        equal = chunk_equals(this->encoding, encoding);
                    441:        free(encoding.ptr);
                    442:        return equal;
                    443: }
                    444: 
                    445: METHOD(certificate_t, get_ref, certificate_t*,
                    446:        private_x509_ocsp_request_t *this)
                    447: {
                    448:        ref_get(&this->ref);
                    449:        return &this->public.interface.interface;
                    450: }
                    451: 
                    452: METHOD(certificate_t, destroy, void,
                    453:        private_x509_ocsp_request_t *this)
                    454: {
                    455:        if (ref_put(&this->ref))
                    456:        {
                    457:                DESTROY_IF((certificate_t*)this->ca);
                    458:                DESTROY_IF(this->requestor);
                    459:                DESTROY_IF(this->cert);
                    460:                DESTROY_IF(this->key);
                    461:                this->candidates->destroy_offset(this->candidates, offsetof(certificate_t, destroy));
                    462:                chunk_free(&this->nonce);
                    463:                chunk_free(&this->encoding);
                    464:                free(this);
                    465:        }
                    466: }
                    467: 
                    468: METHOD(ocsp_request_t, get_nonce, chunk_t,
                    469:        private_x509_ocsp_request_t *this)
                    470: {
                    471:        return this->nonce;
                    472: }
                    473: 
                    474: /**
                    475:  * create an empty but initialized OCSP request
                    476:  */
                    477: static private_x509_ocsp_request_t *create_empty()
                    478: {
                    479:        private_x509_ocsp_request_t *this;
                    480: 
                    481:        INIT(this,
                    482:                .public = {
                    483:                        .interface = {
                    484:                                .interface = {
                    485:                                        .get_type = _get_type,
                    486:                                        .get_subject = _get_subject,
                    487:                                        .get_issuer = _get_issuer,
                    488:                                        .has_subject = _has_subject,
                    489:                                        .has_issuer = _has_issuer,
                    490:                                        .issued_by = _issued_by,
                    491:                                        .get_public_key = _get_public_key,
                    492:                                        .get_validity = _get_validity,
                    493:                                        .get_encoding = _get_encoding,
                    494:                                        .equals = _equals,
                    495:                                        .get_ref = _get_ref,
                    496:                                        .destroy = _destroy,
                    497:                                },
                    498:                                .get_nonce = _get_nonce,
                    499:                        },
                    500:                },
                    501:                .candidates = linked_list_create(),
                    502:                .ref = 1,
                    503:        );
                    504: 
                    505:        return this;
                    506: }
                    507: 
                    508: /**
                    509:  * See header.
                    510:  */
                    511: x509_ocsp_request_t *x509_ocsp_request_gen(certificate_type_t type, va_list args)
                    512: {
                    513:        private_x509_ocsp_request_t *req;
                    514:        certificate_t *cert;
                    515:        private_key_t *private;
                    516:        identification_t *subject;
                    517: 
                    518:        req = create_empty();
                    519:        while (TRUE)
                    520:        {
                    521:                switch (va_arg(args, builder_part_t))
                    522:                {
                    523:                        case BUILD_CA_CERT:
                    524:                                cert = va_arg(args, certificate_t*);
                    525:                                if (cert->get_type(cert) == CERT_X509)
                    526:                                {
                    527:                                        req->ca = (x509_t*)cert->get_ref(cert);
                    528:                                }
                    529:                                continue;
                    530:                        case BUILD_CERT:
                    531:                                cert = va_arg(args, certificate_t*);
                    532:                                if (cert->get_type(cert) == CERT_X509)
                    533:                                {
                    534:                                        req->candidates->insert_last(req->candidates,
                    535:                                                                                                 cert->get_ref(cert));
                    536:                                }
                    537:                                continue;
                    538:                        case BUILD_SIGNING_CERT:
                    539:                                cert = va_arg(args, certificate_t*);
                    540:                                req->cert = cert->get_ref(cert);
                    541:                                continue;
                    542:                        case BUILD_SIGNING_KEY:
                    543:                                private = va_arg(args, private_key_t*);
                    544:                                req->key = private->get_ref(private);
                    545:                                continue;
                    546:                        case BUILD_SUBJECT:
                    547:                                subject = va_arg(args, identification_t*);
                    548:                                req->requestor = subject->clone(subject);
                    549:                                continue;
                    550:                        case BUILD_END:
                    551:                                break;
                    552:                        default:
                    553:                                destroy(req);
                    554:                                return NULL;
                    555:                }
                    556:                break;
                    557:        }
                    558:        if (req->ca)
                    559:        {
                    560:                req->encoding = build_OCSPRequest(req);
                    561:                return &req->public;
                    562:        }
                    563:        destroy(req);
                    564:        return NULL;
                    565: }
                    566: 

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