Annotation of embedaddon/strongswan/src/libstrongswan/plugins/pkcs7/pkcs7_signed_data.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Copyright (C) 2012 Martin Willi
                      3:  * Copyright (C) 2012 revosec AG
                      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 "pkcs7_signed_data.h"
                     17: #include "pkcs7_attributes.h"
                     18: 
                     19: #include <time.h>
                     20: 
                     21: #include <utils/debug.h>
                     22: #include <asn1/oid.h>
                     23: #include <asn1/asn1.h>
                     24: #include <asn1/asn1_parser.h>
                     25: #include <credentials/sets/mem_cred.h>
                     26: #include <credentials/certificates/x509.h>
                     27: #include <credentials/keys/private_key.h>
                     28: 
                     29: typedef struct private_pkcs7_signed_data_t private_pkcs7_signed_data_t;
                     30: 
                     31: /**
                     32:  * Private data of a PKCS#7 signed-data container.
                     33:  */
                     34: struct private_pkcs7_signed_data_t {
                     35: 
                     36:        /**
                     37:         * Implements pkcs7_t.
                     38:         */
                     39:        pkcs7_t public;
                     40: 
                     41:        /**
                     42:         * Signed content data
                     43:         */
                     44:        container_t *content;
                     45: 
                     46:        /**
                     47:         * Encoded PKCS#7 signed-data
                     48:         */
                     49:        chunk_t encoding;
                     50: 
                     51:        /**
                     52:         * list of signerInfos, signerinfo_t
                     53:         */
                     54:        linked_list_t *signerinfos;
                     55: 
                     56:        /**
                     57:         * Contained certificates
                     58:         */
                     59:        mem_cred_t *creds;
                     60: };
                     61: 
                     62: /**
                     63:  * A single signerInfo
                     64:  */
                     65: typedef struct {
                     66: 
                     67:        /**
                     68:         * Signed attributes of signerInfo
                     69:         */
                     70:        pkcs7_attributes_t *attributes;
                     71: 
                     72:        /**
                     73:         * Serial of signing certificate
                     74:         */
                     75:        identification_t *serial;
                     76: 
                     77:        /**
                     78:         * Issuer of signing certificate
                     79:         */
                     80:        identification_t *issuer;
                     81: 
                     82:        /**
                     83:         * EncryptedDigest
                     84:         */
                     85:        chunk_t encrypted_digest;
                     86: 
                     87:        /**
                     88:         * Digesting algorithm OID
                     89:         */
                     90:        int digest_alg;
                     91: 
                     92:        /**
                     93:         * Public key encryption algorithm OID
                     94:         */
                     95:        int enc_alg;
                     96: 
                     97: } signerinfo_t;
                     98: 
                     99: /**
                    100:  * Destroy a signerinfo_t entry
                    101:  */
                    102: void signerinfo_destroy(signerinfo_t *this)
                    103: {
                    104:        DESTROY_IF(this->attributes);
                    105:        DESTROY_IF(this->serial);
                    106:        DESTROY_IF(this->issuer);
                    107:        free(this->encrypted_digest.ptr);
                    108:        free(this);
                    109: }
                    110: 
                    111: /**
                    112:  * ASN.1 definition of the PKCS#7 signedData type
                    113:  */
                    114: static const asn1Object_t signedDataObjects[] = {
                    115:        { 0, "signedData",                                              ASN1_SEQUENCE,          ASN1_NONE }, /*  0 */
                    116:        { 1,   "version",                                               ASN1_INTEGER,           ASN1_BODY }, /*  1 */
                    117:        { 1,   "digestAlgorithms",                              ASN1_SET,                       ASN1_LOOP }, /*  2 */
                    118:        { 2,     "algorithm",                                   ASN1_EOC,                       ASN1_RAW  }, /*  3 */
                    119:        { 1,   "end loop",                                              ASN1_EOC,                       ASN1_END  }, /*  4 */
                    120:        { 1,   "contentInfo",                                   ASN1_EOC,                       ASN1_RAW  }, /*  5 */
                    121:        { 1,   "certificates",                                  ASN1_CONTEXT_C_0,       ASN1_OPT |
                    122:                                                                                                                                ASN1_LOOP }, /*  6 */
                    123:        { 2,      "certificate",                                ASN1_SEQUENCE,          ASN1_OBJ  }, /*  7 */
                    124:        { 1,   "end opt or loop",                               ASN1_EOC,                       ASN1_END  }, /*  8 */
                    125:        { 1,   "crls",                                                  ASN1_CONTEXT_C_1,       ASN1_OPT |
                    126:                                                                                                                                ASN1_LOOP }, /*  9 */
                    127:        { 2,        "crl",                                              ASN1_SEQUENCE,          ASN1_OBJ  }, /* 10 */
                    128:        { 1,   "end opt or loop",                               ASN1_EOC,                       ASN1_END  }, /* 11 */
                    129:        { 1,   "signerInfos",                                   ASN1_SET,                       ASN1_LOOP }, /* 12 */
                    130:        { 2,     "signerInfo",                                  ASN1_SEQUENCE,          ASN1_NONE }, /* 13 */
                    131:        { 3,       "version",                                   ASN1_INTEGER,           ASN1_BODY }, /* 14 */
                    132:        { 3,       "issuerAndSerialNumber",             ASN1_SEQUENCE,          ASN1_BODY }, /* 15 */
                    133:        { 4,         "issuer",                                  ASN1_SEQUENCE,          ASN1_OBJ  }, /* 16 */
                    134:        { 4,         "serial",                                  ASN1_INTEGER,           ASN1_BODY }, /* 17 */
                    135:        { 3,       "digestAlgorithm",                   ASN1_EOC,                       ASN1_RAW  }, /* 18 */
                    136:        { 3,       "authenticatedAttributes",   ASN1_CONTEXT_C_0,       ASN1_OPT |
                    137:                                                                                                                                ASN1_OBJ  }, /* 19 */
                    138:        { 3,       "end opt",                                   ASN1_EOC,                       ASN1_END  }, /* 20 */
                    139:        { 3,       "digestEncryptionAlgorithm", ASN1_EOC,                       ASN1_RAW  }, /* 21 */
                    140:        { 3,       "encryptedDigest",                   ASN1_OCTET_STRING,      ASN1_BODY }, /* 22 */
                    141:        { 3,       "unauthenticatedAttributes", ASN1_CONTEXT_C_1,       ASN1_OPT  }, /* 23 */
                    142:        { 3,       "end opt",                                   ASN1_EOC,                       ASN1_END  }, /* 24 */
                    143:        { 1,   "end loop",                                              ASN1_EOC,                       ASN1_END  }, /* 25 */
                    144:        { 0, "exit",                                                    ASN1_EOC,                       ASN1_EXIT }
                    145: };
                    146: #define PKCS7_VERSION                           1
                    147: #define PKCS7_DIGEST_ALG                        3
                    148: #define PKCS7_CONTENT_INFO                      5
                    149: #define PKCS7_CERT                                      7
                    150: #define PKCS7_SIGNER_INFO                      13
                    151: #define PKCS7_SIGNER_INFO_VERSION      14
                    152: #define PKCS7_ISSUER                           16
                    153: #define PKCS7_SERIAL_NUMBER                    17
                    154: #define PKCS7_DIGEST_ALGORITHM         18
                    155: #define PKCS7_AUTH_ATTRIBUTES          19
                    156: #define PKCS7_DIGEST_ENC_ALGORITHM     21
                    157: #define PKCS7_ENCRYPTED_DIGEST         22
                    158: 
                    159: METHOD(container_t, get_type, container_type_t,
                    160:        private_pkcs7_signed_data_t *this)
                    161: {
                    162:        return CONTAINER_PKCS7_SIGNED_DATA;
                    163: }
                    164: 
                    165: /**
                    166:  * Signature enumerator implementation
                    167:  */
                    168: typedef struct {
                    169:        /** implements enumerator */
                    170:        enumerator_t public;
                    171:        /** inner signerinfos enumerator */
                    172:        enumerator_t *inner;
                    173:        /** currently enumerated auth_cfg */
                    174:        auth_cfg_t *auth;
                    175:        /** currently enumerating signerinfo */
                    176:        signerinfo_t *info;
                    177:        /** reference to container */
                    178:        private_pkcs7_signed_data_t *this;
                    179: } signature_enumerator_t;
                    180: 
                    181: METHOD(enumerator_t, enumerate, bool,
                    182:        signature_enumerator_t *this, va_list args)
                    183: {
                    184:        signerinfo_t *info;
                    185:        signature_scheme_t scheme;
                    186:        hash_algorithm_t algorithm;
                    187:        enumerator_t *enumerator;
                    188:        certificate_t *cert;
                    189:        public_key_t *key;
                    190:        auth_cfg_t *auth, **out;
                    191:        chunk_t chunk, hash, content;
                    192:        hasher_t *hasher;
                    193:        bool valid;
                    194: 
                    195:        VA_ARGS_VGET(args, out);
                    196: 
                    197:        while (this->inner->enumerate(this->inner, &info))
                    198:        {
                    199:                /* clean up previous round */
                    200:                DESTROY_IF(this->auth);
                    201:                this->auth = NULL;
                    202: 
                    203:                scheme = signature_scheme_from_oid(info->digest_alg);
                    204:                if (scheme == SIGN_UNKNOWN)
                    205:                {
                    206:                        DBG1(DBG_LIB, "unsupported signature scheme");
                    207:                        continue;
                    208:                }
                    209:                if (!info->attributes)
                    210:                {
                    211:                        DBG1(DBG_LIB, "no authenticatedAttributes object found");
                    212:                        continue;
                    213:                }
                    214:                if (info->enc_alg != OID_RSA_ENCRYPTION)
                    215:                {
                    216:                        DBG1(DBG_LIB, "only RSA digest encryption supported");
                    217:                        continue;
                    218:                }
                    219: 
                    220:                enumerator = lib->credmgr->create_trusted_enumerator(lib->credmgr,
                    221:                                                                                                KEY_RSA, info->serial, FALSE);
                    222:                while (enumerator->enumerate(enumerator, &cert, &auth))
                    223:                {
                    224:                        if (info->issuer->equals(info->issuer, cert->get_issuer(cert)))
                    225:                        {
                    226:                                key = cert->get_public_key(cert);
                    227:                                if (key)
                    228:                                {
                    229:                                        chunk = info->attributes->get_encoding(info->attributes);
                    230:                                        if (key->verify(key, scheme, NULL, chunk,
                    231:                                                                        info->encrypted_digest))
                    232:                                        {
                    233:                                                this->auth = auth->clone(auth);
                    234:                                                key->destroy(key);
                    235:                                                break;
                    236:                                        }
                    237:                                        key->destroy(key);
                    238:                                }
                    239:                        }
                    240:                }
                    241:                enumerator->destroy(enumerator);
                    242: 
                    243:                if (!this->auth)
                    244:                {
                    245:                        DBG1(DBG_LIB, "unable to verify pkcs7 attributes signature");
                    246:                        continue;
                    247:                }
                    248: 
                    249:                chunk = info->attributes->get_attribute(info->attributes,
                    250:                                                                                                OID_PKCS9_MESSAGE_DIGEST);
                    251:                if (!chunk.len)
                    252:                {
                    253:                        DBG1(DBG_LIB, "messageDigest attribute not found");
                    254:                        continue;
                    255:                }
                    256:                if (!this->this->content->get_data(this->this->content, &content))
                    257:                {
                    258:                        continue;
                    259:                }
                    260: 
                    261:                algorithm = hasher_algorithm_from_oid(info->digest_alg);
                    262:                hasher = lib->crypto->create_hasher(lib->crypto, algorithm);
                    263:                if (!hasher || !hasher->allocate_hash(hasher, content, &hash))
                    264:                {
                    265:                        free(content.ptr);
                    266:                        DESTROY_IF(hasher);
                    267:                        DBG1(DBG_LIB, "hash algorithm %N not supported",
                    268:                                 hash_algorithm_names, algorithm);
                    269:                        continue;
                    270:                }
                    271:                free(content.ptr);
                    272:                hasher->destroy(hasher);
                    273:                DBG3(DBG_LIB, "hash: %B", &hash);
                    274: 
                    275:                valid = chunk_equals_const(chunk, hash);
                    276:                free(hash.ptr);
                    277:                if (!valid)
                    278:                {
                    279:                        DBG1(DBG_LIB, "invalid messageDigest");
                    280:                        continue;
                    281:                }
                    282:                *out = this->auth;
                    283:                this->info = info;
                    284:                return TRUE;
                    285:        }
                    286:        this->info = NULL;
                    287:        return FALSE;
                    288: }
                    289: 
                    290: METHOD(enumerator_t, enumerator_destroy, void,
                    291:        signature_enumerator_t *this)
                    292: {
                    293:        lib->credmgr->remove_local_set(lib->credmgr, &this->this->creds->set);
                    294:        this->inner->destroy(this->inner);
                    295:        DESTROY_IF(this->auth);
                    296:        free(this);
                    297: }
                    298: 
                    299: METHOD(container_t, create_signature_enumerator, enumerator_t*,
                    300:        private_pkcs7_signed_data_t *this)
                    301: {
                    302:        signature_enumerator_t *enumerator;
                    303: 
                    304:        INIT(enumerator,
                    305:                .public = {
                    306:                        .enumerate = enumerator_enumerate_default,
                    307:                        .venumerate = _enumerate,
                    308:                        .destroy = _enumerator_destroy,
                    309:                },
                    310:                .inner = this->signerinfos->create_enumerator(this->signerinfos),
                    311:                .this = this,
                    312:        );
                    313: 
                    314:        lib->credmgr->add_local_set(lib->credmgr, &this->creds->set, FALSE);
                    315:        return &enumerator->public;
                    316: }
                    317: 
                    318: METHOD(pkcs7_t, get_attribute, bool,
                    319:        private_pkcs7_signed_data_t *this, int oid, enumerator_t *enumerator, chunk_t *value)
                    320: {
                    321:        signature_enumerator_t *e;
                    322:        chunk_t chunk;
                    323: 
                    324:        e = (signature_enumerator_t*)enumerator;
                    325:        if (e->info)
                    326:        {
                    327:                chunk = e->info->attributes->get_attribute(e->info->attributes, oid);
                    328:                if (chunk.len)
                    329:                {
                    330:                        *value = chunk_clone(chunk);
                    331:                        return TRUE;
                    332:                }
                    333:        }
                    334:        return FALSE;
                    335: }
                    336: 
                    337: METHOD(pkcs7_t, create_cert_enumerator, enumerator_t*,
                    338:        private_pkcs7_signed_data_t *this)
                    339: {
                    340:        return this->creds->set.create_cert_enumerator(&this->creds->set,
                    341:                                                                                        CERT_ANY, KEY_ANY, NULL, FALSE);
                    342: }
                    343: 
                    344: METHOD(container_t, get_data, bool,
                    345:        private_pkcs7_signed_data_t *this, chunk_t *data)
                    346: {
                    347:        if (this->content)
                    348:        {
                    349:                return this->content->get_data(this->content, data);
                    350:        }
                    351:        return FALSE;
                    352: }
                    353: 
                    354: METHOD(container_t, get_encoding, bool,
                    355:        private_pkcs7_signed_data_t *this, chunk_t *data)
                    356: {
                    357:        *data = chunk_clone(this->encoding);
                    358:        return TRUE;
                    359: }
                    360: 
                    361: METHOD(container_t, destroy, void,
                    362:        private_pkcs7_signed_data_t *this)
                    363: {
                    364:        this->creds->destroy(this->creds);
                    365:        this->signerinfos->destroy_function(this->signerinfos,
                    366:                                                                                (void*)signerinfo_destroy);
                    367:        DESTROY_IF(this->content);
                    368:        free(this->encoding.ptr);
                    369:        free(this);
                    370: }
                    371: 
                    372: /**
                    373:  * Create an empty PKCS#7 signed-data container.
                    374:  */
                    375: static private_pkcs7_signed_data_t* create_empty()
                    376: {
                    377:        private_pkcs7_signed_data_t *this;
                    378: 
                    379:        INIT(this,
                    380:                .public = {
                    381:                        .container = {
                    382:                                .get_type = _get_type,
                    383:                                .create_signature_enumerator = _create_signature_enumerator,
                    384:                                .get_data = _get_data,
                    385:                                .get_encoding = _get_encoding,
                    386:                                .destroy = _destroy,
                    387:                        },
                    388:                        .get_attribute = _get_attribute,
                    389:                        .create_cert_enumerator = _create_cert_enumerator,
                    390:                },
                    391:                .creds = mem_cred_create(),
                    392:                .signerinfos = linked_list_create(),
                    393:        );
                    394: 
                    395:        return this;
                    396: }
                    397: 
                    398: /**
                    399:  * Parse PKCS#7 signed data
                    400:  */
                    401: static bool parse(private_pkcs7_signed_data_t *this, chunk_t content)
                    402: {
                    403:        asn1_parser_t *parser;
                    404:        chunk_t object;
                    405:        int objectID, version;
                    406:        signerinfo_t *info = NULL;
                    407:        bool success = FALSE;
                    408: 
                    409:        parser = asn1_parser_create(signedDataObjects, content);
                    410:        parser->set_top_level(parser, 0);
                    411:        while (parser->iterate(parser, &objectID, &object))
                    412:        {
                    413:                u_int level = parser->get_level(parser);
                    414: 
                    415:                switch (objectID)
                    416:                {
                    417:                        case PKCS7_VERSION:
                    418:                                version = object.len ? (int)*object.ptr : 0;
                    419:                                DBG2(DBG_LIB, "  v%d", version);
                    420:                                break;
                    421:                        case PKCS7_CONTENT_INFO:
                    422:                                this->content = lib->creds->create(lib->creds,
                    423:                                                                                CRED_CONTAINER, CONTAINER_PKCS7,
                    424:                                                                                BUILD_BLOB_ASN1_DER, object, BUILD_END);
                    425:                                break;
                    426:                        case PKCS7_CERT:
                    427:                        {
                    428:                                certificate_t *cert;
                    429: 
                    430:                                DBG2(DBG_LIB, "  parsing pkcs7-wrapped certificate");
                    431:                                cert = lib->creds->create(lib->creds,
                    432:                                                                                  CRED_CERTIFICATE, CERT_X509,
                    433:                                                                                  BUILD_BLOB_ASN1_DER, object,
                    434:                                                                                  BUILD_END);
                    435:                                if (cert)
                    436:                                {
                    437:                                        this->creds->add_cert(this->creds, FALSE, cert);
                    438:                                }
                    439:                                break;
                    440:                        }
                    441:                        case PKCS7_SIGNER_INFO:
                    442:                                INIT(info,
                    443:                                        .digest_alg = OID_UNKNOWN,
                    444:                                        .enc_alg = OID_UNKNOWN,
                    445:                                );
                    446:                                this->signerinfos->insert_last(this->signerinfos, info);
                    447:                                break;
                    448:                        case PKCS7_SIGNER_INFO_VERSION:
                    449:                                version = object.len ? (int)*object.ptr : 0;
                    450:                                DBG2(DBG_LIB, "  v%d", version);
                    451:                                break;
                    452:                        case PKCS7_ISSUER:
                    453:                                info->issuer = identification_create_from_encoding(
                    454:                                                                                                                ID_DER_ASN1_DN, object);
                    455:                                break;
                    456:                        case PKCS7_SERIAL_NUMBER:
                    457:                                info->serial = identification_create_from_encoding(
                    458:                                                                                                                ID_KEY_ID, object);
                    459:                                break;
                    460:                        case PKCS7_AUTH_ATTRIBUTES:
                    461:                                *object.ptr = ASN1_SET;
                    462:                                info->attributes = pkcs7_attributes_create_from_chunk(
                    463:                                                                                                                object, level+1);
                    464:                                *object.ptr = ASN1_CONTEXT_C_0;
                    465:                                break;
                    466:                        case PKCS7_DIGEST_ALGORITHM:
                    467:                                info->digest_alg = asn1_parse_algorithmIdentifier(object,
                    468:                                                                                                                level, NULL);
                    469:                                break;
                    470:                        case PKCS7_DIGEST_ENC_ALGORITHM:
                    471:                                info->enc_alg = asn1_parse_algorithmIdentifier(object,
                    472:                                                                                                                level, NULL);
                    473:                                break;
                    474:                        case PKCS7_ENCRYPTED_DIGEST:
                    475:                                info->encrypted_digest = chunk_clone(object);
                    476:                                break;
                    477:                }
                    478:        }
                    479:        success = parser->success(parser);
                    480:        parser->destroy(parser);
                    481: 
                    482:        return success;
                    483: }
                    484: 
                    485: /**
                    486:  * See header.
                    487:  */
                    488: pkcs7_t *pkcs7_signed_data_load(chunk_t encoding, chunk_t content)
                    489: {
                    490:        private_pkcs7_signed_data_t *this = create_empty();
                    491: 
                    492:        this->encoding = chunk_clone(encoding);
                    493:        if (!parse(this, content))
                    494:        {
                    495:                destroy(this);
                    496:                return NULL;
                    497:        }
                    498:        return &this->public;
                    499: }
                    500: 
                    501: /**
                    502:  * build a DER-encoded issuerAndSerialNumber object
                    503:  */
                    504: static chunk_t build_issuerAndSerialNumber(certificate_t *cert)
                    505: {
                    506:        identification_t *issuer = cert->get_issuer(cert);
                    507:        chunk_t serial = chunk_empty;
                    508: 
                    509:        if (cert->get_type(cert) == CERT_X509)
                    510:        {
                    511:                x509_t *x509 = (x509_t*)cert;
                    512:                serial = x509->get_serial(x509);
                    513:        }
                    514: 
                    515:        return asn1_wrap(ASN1_SEQUENCE, "cm",
                    516:                                         issuer->get_encoding(issuer),
                    517:                                         asn1_integer("c", serial));
                    518: }
                    519: 
                    520: /**
                    521:  * Generate a new PKCS#7 signed-data container
                    522:  */
                    523: static bool generate(private_pkcs7_signed_data_t *this, private_key_t *key,
                    524:                                         certificate_t *cert, hash_algorithm_t alg,
                    525:                                         pkcs7_attributes_t *pkcs9)
                    526: {
                    527:        chunk_t authenticatedAttributes = chunk_empty;
                    528:        chunk_t encryptedDigest = chunk_empty;
                    529:        chunk_t data, signerInfo, encoding = chunk_empty;
                    530:        chunk_t messageDigest, signingTime, attributes;
                    531:        signature_scheme_t scheme;
                    532:        hasher_t *hasher;
                    533:        time_t now;
                    534:        int digest_oid;
                    535: 
                    536:        digest_oid = hasher_algorithm_to_oid(alg);
                    537:        scheme = signature_scheme_from_oid(digest_oid);
                    538: 
                    539:        if (!this->content->get_data(this->content, &data))
                    540:        {
                    541:                return FALSE;
                    542:        }
                    543: 
                    544:        hasher = lib->crypto->create_hasher(lib->crypto, alg);
                    545:        if (!hasher || !hasher->allocate_hash(hasher, data, &messageDigest))
                    546:        {
                    547:                DESTROY_IF(hasher);
                    548:                DBG1(DBG_LIB, "  hash algorithm %N not support",
                    549:                         hash_algorithm_names, alg);
                    550:                free(data.ptr);
                    551:                return FALSE;
                    552:        }
                    553:        hasher->destroy(hasher);
                    554:        pkcs9->add_attribute(pkcs9,
                    555:                                        OID_PKCS9_MESSAGE_DIGEST,
                    556:                                        asn1_wrap(ASN1_OCTET_STRING, "m", messageDigest));
                    557: 
                    558:        /* take the current time as signingTime */
                    559:        now = time(NULL);
                    560:        signingTime = asn1_from_time(&now, ASN1_UTCTIME);
                    561:        pkcs9->add_attribute(pkcs9, OID_PKCS9_SIGNING_TIME, signingTime);
                    562:        pkcs9->add_attribute(pkcs9, OID_PKCS9_CONTENT_TYPE,
                    563:                                                 asn1_build_known_oid(OID_PKCS7_DATA));
                    564: 
                    565:        attributes = pkcs9->get_encoding(pkcs9);
                    566: 
                    567:        if (!key->sign(key, scheme, NULL, attributes, &encryptedDigest))
                    568:        {
                    569:                free(data.ptr);
                    570:                return FALSE;
                    571:        }
                    572:        authenticatedAttributes = chunk_clone(attributes);
                    573:        *authenticatedAttributes.ptr = ASN1_CONTEXT_C_0;
                    574: 
                    575:        free(data.ptr);
                    576:        if (encryptedDigest.ptr)
                    577:        {
                    578:                encryptedDigest = asn1_wrap(ASN1_OCTET_STRING, "m", encryptedDigest);
                    579:        }
                    580:        signerInfo = asn1_wrap(ASN1_SEQUENCE, "cmmmmm",
                    581:                                        ASN1_INTEGER_1,
                    582:                                        build_issuerAndSerialNumber(cert),
                    583:                                        asn1_algorithmIdentifier(digest_oid),
                    584:                                        authenticatedAttributes,
                    585:                                        asn1_algorithmIdentifier(OID_RSA_ENCRYPTION),
                    586:                                        encryptedDigest);
                    587: 
                    588:        if (!cert->get_encoding(cert, CERT_ASN1_DER, &encoding))
                    589:        {
                    590:                free(signerInfo.ptr);
                    591:                return FALSE;
                    592:        }
                    593:        if (!this->content->get_encoding(this->content, &data))
                    594:        {
                    595:                free(encoding.ptr);
                    596:                free(signerInfo.ptr);
                    597:                return FALSE;
                    598:        }
                    599: 
                    600:        this->encoding = asn1_wrap(ASN1_SEQUENCE, "mm",
                    601:                asn1_build_known_oid(OID_PKCS7_SIGNED_DATA),
                    602:                asn1_wrap(ASN1_CONTEXT_C_0, "m",
                    603:                        asn1_wrap(ASN1_SEQUENCE, "cmmmm",
                    604:                                ASN1_INTEGER_1,
                    605:                                asn1_wrap(ASN1_SET, "m", asn1_algorithmIdentifier(digest_oid)),
                    606:                                data,
                    607:                                asn1_wrap(ASN1_CONTEXT_C_0, "m", encoding),
                    608:                                asn1_wrap(ASN1_SET, "m", signerInfo))));
                    609: 
                    610: 
                    611:        pkcs9->destroy(pkcs9);
                    612:        /* TODO: create signerInfos entry */
                    613:        return TRUE;
                    614: }
                    615: 
                    616: /**
                    617:  * See header.
                    618:  */
                    619: pkcs7_t *pkcs7_signed_data_gen(container_type_t type, va_list args)
                    620: {
                    621:        private_pkcs7_signed_data_t *this;
                    622:        chunk_t blob = chunk_empty;
                    623:        hash_algorithm_t alg = HASH_SHA1;
                    624:        private_key_t *key = NULL;
                    625:        certificate_t *cert = NULL;
                    626:        pkcs7_attributes_t *pkcs9;
                    627:        chunk_t value;
                    628:        int oid;
                    629: 
                    630:        pkcs9 = pkcs7_attributes_create();
                    631: 
                    632:        while (TRUE)
                    633:        {
                    634:                switch (va_arg(args, builder_part_t))
                    635:                {
                    636:                        case BUILD_SIGNING_KEY:
                    637:                                key = va_arg(args, private_key_t*);
                    638:                                continue;
                    639:                        case BUILD_SIGNING_CERT:
                    640:                                cert = va_arg(args, certificate_t*);
                    641:                                continue;
                    642:                        case BUILD_DIGEST_ALG:
                    643:                                alg = va_arg(args, int);
                    644:                                continue;
                    645:                        case BUILD_BLOB:
                    646:                                blob = va_arg(args, chunk_t);
                    647:                                continue;
                    648:                        case BUILD_PKCS7_ATTRIBUTE:
                    649:                                oid = va_arg(args, int);
                    650:                                value = va_arg(args, chunk_t);
                    651:                                pkcs9->add_attribute(pkcs9, oid, chunk_clone(value));
                    652:                                continue;
                    653:                        case BUILD_END:
                    654:                                break;
                    655:                        default:
                    656:                                pkcs9->destroy(pkcs9);
                    657:                                return NULL;
                    658:                }
                    659:                break;
                    660:        }
                    661:        if (blob.len && key && cert)
                    662:        {
                    663:                this = create_empty();
                    664: 
                    665:                this->creds->add_cert(this->creds, FALSE, cert->get_ref(cert));
                    666:                this->content = lib->creds->create(lib->creds,
                    667:                                                                                   CRED_CONTAINER, CONTAINER_PKCS7_DATA,
                    668:                                                                                   BUILD_BLOB, blob, BUILD_END);
                    669: 
                    670:                if (this->content && generate(this, key, cert, alg, pkcs9))
                    671:                {
                    672:                        return &this->public;
                    673:                }
                    674:                pkcs9->destroy(pkcs9);
                    675:                destroy(this);
                    676:        }
                    677:        else
                    678:        {
                    679:                pkcs9->destroy(pkcs9);
                    680:        }
                    681:        return NULL;
                    682: }

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