Coverage Report

Created: 2026-06-10 06:49

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opensc/openpace/src/eac_asn1.c
Line
Count
Source
1
/*
2
 * Copyright (c) 2010-2012 Dominik Oepen and Frank Morgner
3
 *
4
 * This file is part of OpenPACE.
5
 *
6
 * OpenPACE is free software: you can redistribute it and/or modify it under
7
 * the terms of the GNU General Public License as published by the Free
8
 * Software Foundation, either version 3 of the License, or (at your option)
9
 * any later version.
10
 *
11
 * OpenPACE is distributed in the hope that it will be useful, but WITHOUT ANY
12
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
13
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
14
 * details.
15
 *
16
 * You should have received a copy of the GNU General Public License along with
17
 * OpenPACE.  If not, see <http://www.gnu.org/licenses/>.
18
 *
19
 * Additional permission under GNU GPL version 3 section 7
20
 *
21
 * If you modify this Program, or any covered work, by linking or combining it
22
 * with OpenSSL (or a modified version of that library), containing
23
 * parts covered by the terms of OpenSSL's license, the licensors of
24
 * this Program grant you additional permission to convey the resulting work.
25
 * Corresponding Source for a non-source form of such a combination shall include
26
 * the source code for the parts of OpenSSL used as well as that of the
27
 * covered work.
28
 *
29
 * If you modify this Program, or any covered work, by linking or combining it
30
 * with OpenSC (or a modified version of that library), containing
31
 * parts covered by the terms of OpenSC's license, the licensors of
32
 * this Program grant you additional permission to convey the resulting work. 
33
 * Corresponding Source for a non-source form of such a combination shall include
34
 * the source code for the parts of OpenSC used as well as that of the
35
 * covered work.
36
 */
37
38
/**
39
 * @file eac_asn1.c
40
 * @brief ASN.1 structures related to PACE
41
 *
42
 * @author Dominik Oepen <oepen@informatik.hu-berlin.de>
43
 * @author Frank Morgner <frankmorgner@gmail.com>
44
 */
45
46
#ifdef HAVE_CONFIG_H
47
#include "config.h"
48
#endif
49
50
#include "ca_lib.h"
51
#include "eac_asn1.h"
52
#include "eac_dh.h"
53
#include "eac_err.h"
54
#include "eac_util.h"
55
#include "misc.h"
56
#include "pace_lib.h"
57
#include <eac/eac.h>
58
#include <eac/pace.h>
59
#include <eac/ri.h>
60
#include <openssl/asn1.h>
61
#include <openssl/dh.h>
62
#include <openssl/ec.h>
63
#include <openssl/objects.h>
64
#include <openssl/obj_mac.h>
65
66
/** PACEInfo structure */
67
typedef struct pace_info_st {
68
    /** OID of the algorithm to be used */
69
    ASN1_OBJECT *protocol;
70
    /** Protocol Version number. Version number 1 is deprecated, version 2 is
71
        recommended */
72
    ASN1_INTEGER *version;
73
    /** Indicates the domain parameter identifier. named parameterID in BSI TR-03110 */
74
    ASN1_INTEGER *keyID;
75
    } PACE_INFO;
76
77
/** Algorithm Identifier structure */
78
typedef struct algorithm_identifier_st {
79
    /** OID of the algorithm */
80
    ASN1_OBJECT *algorithm;
81
    ASN1_TYPE *parameters;
82
} ALGORITHM_IDENTIFIER;
83
84
/** Subject Public Key Info structure */
85
typedef struct subject_public_key_info_st {
86
    ALGORITHM_IDENTIFIER *algorithmIdentifier;
87
    ASN1_BIT_STRING *subjectPublicKey;
88
} SUBJECT_PUBLIC_KEY_INFO;
89
90
/** Domain parameter structure */
91
typedef struct pace_dp_info_st {
92
    /** OID of the type of domain parameters*/
93
    ASN1_OBJECT *protocol;
94
    /** The actual domain parameters */
95
    ALGORITHM_IDENTIFIER *aid;
96
    /** Optional: specifies the local domain parameters if multiple sets of domain
97
        parameters are provided. named parameterID in BSI TR-03110 */
98
    ASN1_INTEGER *keyID;
99
} PACE_DP_INFO;
100
101
/** ChipAuthenticationInfo structure */
102
typedef struct ca_info_st {
103
    /** OID */
104
    ASN1_OBJECT *protocol;
105
    /** Protocol Version number. Currently Version 1 and Version 2 are supported */
106
    ASN1_INTEGER *version;
107
    /** keyID MAY be used to indicate the local key identifier */
108
    ASN1_INTEGER *keyID;
109
} CA_INFO;
110
111
/** CA Domain parameter structure */
112
typedef struct ca_dp_info_st {
113
    /** OID of the type of domain parameters*/
114
    ASN1_OBJECT *protocol;
115
    /** The actual domain parameters */
116
    ALGORITHM_IDENTIFIER *aid;
117
    /** Optional: specifies the local domain parameters if multiple sets of domain
118
        parameters are provided */
119
    ASN1_INTEGER *keyID;
120
} CA_DP_INFO;
121
122
/** CA public key info */
123
typedef struct ca_public_key_info_st {
124
    /** OID of the type of domain parameters*/
125
    ASN1_OBJECT *protocol;
126
    /** The actual public key */
127
    SUBJECT_PUBLIC_KEY_INFO *chipAuthenticationPublicKeyInfo;
128
    /** Optional: specifies the local domain parameters if multiple sets of domain
129
        parameters are provided */
130
    ASN1_INTEGER *keyID;
131
} CA_PUBLIC_KEY_INFO;
132
133
/** File ID */
134
typedef struct file_id_st {
135
    /** File identifier */
136
    ASN1_OCTET_STRING *fid;
137
    /** Short file ifentifier */
138
    ASN1_OCTET_STRING *sfid;
139
} FILE_ID;
140
141
/** TerminalAuthenticationInfo */
142
typedef struct ta_info_st {
143
    /** OID */
144
    ASN1_OBJECT *protocol;
145
    /** Protocol Version number. Currently Version 1 and Version 2 are supported */
146
    ASN1_INTEGER *version;
147
    /** FileIdentifier of EF.CVCA */
148
    FILE_ID *efCVCA;
149
} TA_INFO;
150
151
/** ProtocolParams */
152
typedef struct protocol_params_st {
153
    /* Protocol version. Currently only version 1 is supported */
154
    ASN1_INTEGER *version;
155
    /** keyID identifies the private key that shall be used */
156
    ASN1_INTEGER *keyID;
157
    /** Indicates whether explicit authorization is required to use the
158
     * corresponding secret key */
159
    ASN1_BOOLEAN *authorizedOnly;
160
} PROTOCOL_PARAMS;
161
162
/** Restricted Authentication Info*/
163
typedef struct ri_info_st {
164
    /** OID */
165
    ASN1_OBJECT *protocol;
166
    /** Protocol parameters */
167
    PROTOCOL_PARAMS *params;
168
    /** indicates the maximum length of the supported sector
169
     * specific public keys */
170
    ASN1_INTEGER *maxKeyLen;
171
} RI_INFO;
172
173
/** RI domain parameter info */
174
typedef struct ri_dp_info_st {
175
    /** OID of the type of domain parameters*/
176
    ASN1_OBJECT *protocol;
177
    /** The actual domain parameters */
178
    ALGORITHM_IDENTIFIER *aid;
179
} RI_DP_INFO;
180
181
/** Card Info Locator */
182
typedef struct card_info_locator_st {
183
    /** OID */
184
    ASN1_OBJECT *protocol;
185
    ASN1_IA5STRING *url;
186
    FILE_ID *efCardInfo;
187
} CARD_INFO_LOCATOR;
188
189
ASN1_SEQUENCE(PACE_INFO) = {
190
    ASN1_SIMPLE(PACE_INFO, protocol, ASN1_OBJECT),
191
    ASN1_SIMPLE(PACE_INFO, version, ASN1_INTEGER),
192
    ASN1_OPT(PACE_INFO, keyID, ASN1_INTEGER)
193
} ASN1_SEQUENCE_END(PACE_INFO)
194
195
IMPLEMENT_ASN1_FUNCTIONS(PACE_INFO)
196
197
ASN1_SEQUENCE(ALGORITHM_IDENTIFIER) = {
198
    ASN1_SIMPLE(ALGORITHM_IDENTIFIER, algorithm, ASN1_OBJECT),
199
    ASN1_SIMPLE(ALGORITHM_IDENTIFIER, parameters, ASN1_ANY)
200
} ASN1_SEQUENCE_END(ALGORITHM_IDENTIFIER)
201
202
ASN1_SEQUENCE(SUBJECT_PUBLIC_KEY_INFO) = {
203
        ASN1_SIMPLE(SUBJECT_PUBLIC_KEY_INFO, algorithmIdentifier, ALGORITHM_IDENTIFIER),
204
        ASN1_SIMPLE(SUBJECT_PUBLIC_KEY_INFO, subjectPublicKey, ASN1_BIT_STRING)
205
} ASN1_SEQUENCE_END(SUBJECT_PUBLIC_KEY_INFO)
206
207
/* PACEDomainParameterInfo */
208
ASN1_SEQUENCE(PACE_DP_INFO) = {
209
    ASN1_SIMPLE(PACE_DP_INFO, protocol, ASN1_OBJECT),
210
    ASN1_SIMPLE(PACE_DP_INFO, aid, ALGORITHM_IDENTIFIER),
211
    ASN1_OPT(PACE_DP_INFO, keyID, ASN1_INTEGER)
212
} ASN1_SEQUENCE_END(PACE_DP_INFO)
213
214
IMPLEMENT_ASN1_FUNCTIONS(PACE_DP_INFO)
215
216
/* ChipAuthenticationInfo */
217
ASN1_SEQUENCE(CA_INFO) = {
218
    ASN1_SIMPLE(CA_INFO, protocol, ASN1_OBJECT),
219
    ASN1_SIMPLE(CA_INFO, version, ASN1_INTEGER),
220
    ASN1_OPT(CA_INFO, keyID, ASN1_INTEGER)
221
} ASN1_SEQUENCE_END(CA_INFO)
222
IMPLEMENT_ASN1_FUNCTIONS(CA_INFO)
223
224
/* ChipAuthenticationDomainParameterInfo */
225
ASN1_SEQUENCE(CA_DP_INFO) = {
226
    ASN1_SIMPLE(CA_DP_INFO, protocol, ASN1_OBJECT),
227
    ASN1_SIMPLE(CA_DP_INFO, aid, ALGORITHM_IDENTIFIER),
228
    ASN1_OPT(CA_DP_INFO, keyID, ASN1_INTEGER)
229
} ASN1_SEQUENCE_END(CA_DP_INFO)
230
IMPLEMENT_ASN1_FUNCTIONS(CA_DP_INFO)
231
232
/* ChipAuthenticationPublicKeyInfo */
233
ASN1_SEQUENCE(CA_PUBLIC_KEY_INFO) = {
234
        ASN1_SIMPLE(CA_PUBLIC_KEY_INFO, protocol, ASN1_OBJECT),
235
        ASN1_SIMPLE(CA_PUBLIC_KEY_INFO, chipAuthenticationPublicKeyInfo, SUBJECT_PUBLIC_KEY_INFO),
236
        ASN1_OPT(CA_PUBLIC_KEY_INFO, keyID, ASN1_INTEGER)
237
} ASN1_SEQUENCE_END(CA_PUBLIC_KEY_INFO)
238
IMPLEMENT_ASN1_FUNCTIONS(CA_PUBLIC_KEY_INFO)
239
240
/* FileId */
241
ASN1_SEQUENCE(FILE_ID) = {
242
    ASN1_SIMPLE(FILE_ID, fid, ASN1_OCTET_STRING),
243
    ASN1_OPT(FILE_ID, sfid, ASN1_OCTET_STRING)
244
} ASN1_SEQUENCE_END(FILE_ID)
245
246
/* TerminalAuthenticationInfo */
247
ASN1_SEQUENCE(TA_INFO) = {
248
    ASN1_SIMPLE(TA_INFO, protocol, ASN1_OBJECT),
249
    ASN1_SIMPLE(TA_INFO, version, ASN1_INTEGER),
250
    ASN1_OPT(TA_INFO, efCVCA, FILE_ID)
251
} ASN1_SEQUENCE_END(TA_INFO)
252
IMPLEMENT_ASN1_FUNCTIONS(TA_INFO)
253
254
/* ProtocolParams */
255
ASN1_SEQUENCE(PROTOCOL_PARAMS) = {
256
    ASN1_SIMPLE(PROTOCOL_PARAMS, version, ASN1_INTEGER),
257
    ASN1_SIMPLE(PROTOCOL_PARAMS, keyID, ASN1_INTEGER),
258
    ASN1_SIMPLE(PROTOCOL_PARAMS, authorizedOnly, ASN1_BOOLEAN)
259
} ASN1_SEQUENCE_END(PROTOCOL_PARAMS)
260
261
/* RestrictedIdentificationInfo */
262
ASN1_SEQUENCE(RI_INFO) = {
263
    ASN1_SIMPLE(RI_INFO, protocol, ASN1_OBJECT),
264
    ASN1_SIMPLE(RI_INFO, params, PROTOCOL_PARAMS),
265
    ASN1_OPT(RI_INFO, maxKeyLen, ASN1_INTEGER)
266
} ASN1_SEQUENCE_END(RI_INFO)
267
IMPLEMENT_ASN1_FUNCTIONS(RI_INFO)
268
269
/* RestrictedIdentificationDomainParameterInfo */
270
ASN1_SEQUENCE(RI_DP_INFO) = {
271
    ASN1_SIMPLE(RI_DP_INFO, protocol, ASN1_OBJECT),
272
    ASN1_SIMPLE(RI_DP_INFO, aid, ALGORITHM_IDENTIFIER),
273
} ASN1_SEQUENCE_END(RI_DP_INFO)
274
IMPLEMENT_ASN1_FUNCTIONS(RI_DP_INFO)
275
276
/* CardInfoLocator */
277
ASN1_SEQUENCE(CARD_INFO_LOCATOR) = {
278
    ASN1_SIMPLE(CARD_INFO_LOCATOR, protocol, ASN1_OBJECT),
279
    ASN1_SIMPLE(CARD_INFO_LOCATOR, url, ASN1_IA5STRING),
280
    ASN1_OPT(CARD_INFO_LOCATOR, efCardInfo, FILE_ID)
281
} ASN1_SEQUENCE_END(CARD_INFO_LOCATOR)
282
283
284
285
static EC_KEY *
286
ecpkparameters2eckey(ASN1_TYPE *ec_params)
287
0
{
288
0
    EC_GROUP *group = NULL;
289
0
    EC_KEY *ec = NULL;
290
0
    int length, fail = 1;
291
0
    unsigned char *encoded = NULL;
292
0
    const unsigned char *p;
293
294
0
    check(ec_params && ec_params->type == V_ASN1_SEQUENCE,
295
0
            "Invalid arguments");
296
297
    /* unfortunately we need to re-pack and re-parse the ECPKPARAMETERS,
298
     * because there is no official API for using it directly (see
299
     * openssl/crypto/ec/ec.h) */
300
0
    length = i2d_ASN1_TYPE(ec_params, &encoded);
301
0
    p = encoded;
302
0
    check(length > 0 && d2i_ECPKParameters(&group, &p, length),
303
0
            "Could not decode EC parameters");
304
305
0
    ec = EC_KEY_new();
306
0
    check(ec && EC_KEY_set_group(ec, group),
307
0
            "Could not initialize key object");
308
309
0
    fail = 0;
310
311
0
err:
312
0
    if (group)
313
0
        EC_GROUP_free(group);
314
0
    OPENSSL_free(encoded);
315
0
    if (fail) {
316
0
        if (ec)
317
0
            EC_KEY_free(ec);
318
0
        ec = NULL;
319
0
    }
320
0
    return ec;
321
0
}
322
323
static DH *
324
dhparams2dh(ASN1_TYPE *dh_params)
325
0
{
326
0
    DH *dh = NULL;
327
0
    int length = 1;
328
0
    unsigned char *encoded = NULL;
329
0
    const unsigned char *p;
330
331
0
    check(dh_params && dh_params->type == V_ASN1_SEQUENCE,
332
0
            "Invalid arguments");
333
334
    /* unfortunately we need to re-pack and re-parse the DHparams,
335
     * because there is no official API for using it directly (see
336
     * openssl/crypto/dh/dh.h) */
337
0
    length = i2d_ASN1_TYPE(dh_params, &encoded);
338
0
    p = encoded;
339
0
    check(length > 0 && d2i_DHparams(&dh, &p, length),
340
0
            "Could not decode DH parameters");
341
342
0
err:
343
0
    OPENSSL_free(encoded);
344
0
    return dh;
345
0
}
346
347
static EVP_PKEY *
348
aid2pkey(EVP_PKEY **key, ALGORITHM_IDENTIFIER *aid, BN_CTX *bn_ctx)
349
0
{
350
0
    EC_KEY *tmp_ec;
351
0
    DH *tmp_dh;
352
0
    EVP_PKEY *tmp_key = NULL, *ret = NULL;
353
0
    char obj_txt[32];
354
0
    int nid;
355
356
    /* If there is no key, allocate memory */
357
0
    if (!key || !*key) {
358
0
        tmp_key = EVP_PKEY_new();
359
0
        if (!tmp_key)
360
0
            goto err;
361
0
    } else
362
0
        tmp_key = *key;
363
364
    /* Extract actual parameters */
365
0
    nid = OBJ_obj2nid(aid->algorithm);
366
0
    if (       nid == NID_dhpublicnumber) {
367
0
        tmp_dh = dhparams2dh(aid->parameters);
368
0
        check(tmp_dh, "Could not decode DH key");
369
0
        EVP_PKEY_set1_DH(tmp_key, tmp_dh);
370
0
        DH_free(tmp_dh);
371
372
0
    } else if (nid == NID_X9_62_id_ecPublicKey
373
0
            || nid == NID_ecka_dh_SessionKDF_DES3
374
0
            || nid == NID_ecka_dh_SessionKDF_AES128
375
0
            || nid == NID_ecka_dh_SessionKDF_AES192
376
0
            || nid == NID_ecka_dh_SessionKDF_AES256) {
377
0
        tmp_ec = ecpkparameters2eckey(aid->parameters);
378
0
        check(tmp_ec, "Could not decode EC key");
379
0
        EVP_PKEY_set1_EC_KEY(tmp_key, tmp_ec);
380
0
        EC_KEY_free(tmp_ec);
381
382
0
    } else if (nid == NID_standardizedDomainParameters) {
383
0
        check(aid->parameters->type == V_ASN1_INTEGER,
384
0
                "Invalid data");
385
0
        check(EVP_PKEY_set_std_dp(tmp_key,
386
0
                    ASN1_INTEGER_get(aid->parameters->value.integer)),
387
0
                "Could not decode standardized domain parameter")
388
389
0
    } else {
390
0
        OBJ_obj2txt(obj_txt, sizeof obj_txt, aid->algorithm, 0);
391
0
        debug("Unknown Identifier (%s) for %s", OBJ_nid2sn(nid), obj_txt);
392
0
    }
393
394
0
    ret = tmp_key;
395
0
    if (key)
396
0
        *key = tmp_key;
397
398
0
err:
399
0
    if (tmp_key && tmp_key != ret) {
400
0
        EVP_PKEY_free(tmp_key);
401
0
    }
402
403
0
    return ret;
404
0
}
405
406
407
0
#define get_ctx_by_id(ctx, stack, _id) \
408
0
{ \
409
0
    int __i, __count; \
410
0
    __count = sk_num((_STACK*) stack); \
411
0
    for (__i = 0; __i < __count; __i++) { \
412
0
        ctx = sk_value((_STACK*) stack, __i); \
413
0
        if (ctx && ctx->id == _id) { \
414
0
            break; \
415
0
        } \
416
0
    } \
417
0
    if (__i >= __count) { \
418
0
        ctx = NULL; \
419
0
    } \
420
0
}
421
422
0
#define get_ctx_by_keyID(ctx, stack, keyID, structure) \
423
0
{ \
424
0
    int __id; \
425
0
    if (keyID) { \
426
0
        __id = (int) ASN1_INTEGER_get(keyID); \
427
0
    }  \
428
0
    else { \
429
0
        __id = -1; \
430
0
    } \
431
0
    /* lookup the context in the stack identified by info's keyID */ \
432
0
    get_ctx_by_id(ctx, stack, __id); \
433
0
    \
434
0
    /* if no context was found, create one and push it onto the stack */ \
435
0
    if (!ctx) { \
436
0
        ctx = structure##_new(); \
437
0
        if (ctx) { \
438
0
            if (!sk_push((_STACK *) stack, ctx)) { \
439
0
                structure##_clear_free(ctx); \
440
0
                ctx = NULL; \
441
0
            } else { \
442
0
                /* created and pushed successfully, now initialize id */ \
443
0
                if(keyID) { \
444
0
                    ctx->id = __id; \
445
0
                } else { \
446
0
                    ctx->id = -1; \
447
0
                } \
448
0
            } \
449
0
        } \
450
0
    } \
451
0
}
452
453
int
454
EAC_CTX_init_ef_cardaccess(const unsigned char * in, size_t in_len,
455
        EAC_CTX *ctx)
456
0
{
457
0
    ASN1_INTEGER *i = NULL;
458
0
    ASN1_OBJECT *oid = NULL;
459
0
    const unsigned char *pubkey;
460
0
    size_t pubkey_len;
461
0
    CA_CTX *ca_ctx = NULL;
462
0
    CA_DP_INFO *tmp_ca_dp_info = NULL;
463
0
    CA_INFO *tmp_ca_info = NULL;
464
0
    CA_PUBLIC_KEY_INFO *ca_public_key_info = NULL;
465
0
    PACE_CTX *pace_ctx = NULL;
466
0
    PACE_DP_INFO *tmp_dp_info = NULL;
467
0
    PACE_INFO *tmp_info = NULL;
468
0
    RI_CTX *ri_ctx = NULL;
469
0
    RI_DP_INFO *tmp_ri_dp_info = NULL;
470
0
    RI_INFO *tmp_ri_info = NULL;
471
0
    TA_INFO *tmp_ta_info = NULL;
472
0
    char obj_txt[32];
473
0
    const unsigned char *info_start;
474
0
    int tag, class, nid, _count, _i, r = 0, has_no_pace_dp_info = 1;
475
0
    long data_len, info_len;
476
0
    unsigned int todo = 0;
477
478
0
    check((in && ctx && ctx->pace_ctxs && ctx->ca_ctxs && ctx->ri_ctxs),
479
0
        "Invalid arguments");
480
481
    /* We need to manually extract all members of the SET OF SecurityInfos,
482
     * because some files contain junk and look something like this:
483
     *
484
     *      SET { SecurityInfo, ..., SecurityInfo } , junk
485
     *
486
     * As far as we know, there is no way of telling OpenSSL to simply ignore
487
     * the junk in d2i_* functions. That's why we iterate manually through
488
     * the set */
489
490
0
    check(!(0x80 & ASN1_get_object(&in, &data_len, &tag, &class, in_len))
491
0
            && tag == V_ASN1_SET,
492
0
            "Invalid data");
493
494
0
    todo = data_len;
495
496
0
    while (todo > 0) {
497
0
        info_start = in;
498
499
0
        if (!(ASN1_get_object(&in, &data_len, &tag, &class, todo))
500
0
                || tag != V_ASN1_SEQUENCE) {
501
            /* we've reached the junk */
502
0
            break;
503
0
        }
504
505
0
        info_len = (in-info_start) + data_len;
506
507
0
        check(d2i_ASN1_OBJECT(&oid, &in, data_len),
508
0
                "Invalid oid");
509
510
0
        in = info_start;
511
512
0
        nid = OBJ_obj2nid(oid);
513
0
        if (       nid == NID_id_PACE_DH_GM_3DES_CBC_CBC
514
0
                || nid == NID_id_PACE_DH_IM_3DES_CBC_CBC
515
0
                || nid == NID_id_PACE_ECDH_GM_3DES_CBC_CBC
516
0
                || nid == NID_id_PACE_ECDH_IM_3DES_CBC_CBC
517
0
                || nid == NID_id_PACE_DH_GM_AES_CBC_CMAC_128
518
0
                || nid == NID_id_PACE_DH_GM_AES_CBC_CMAC_192
519
0
                || nid == NID_id_PACE_DH_GM_AES_CBC_CMAC_256
520
0
                || nid == NID_id_PACE_DH_IM_AES_CBC_CMAC_128
521
0
                || nid == NID_id_PACE_DH_IM_AES_CBC_CMAC_192
522
0
                || nid == NID_id_PACE_DH_IM_AES_CBC_CMAC_256
523
0
                || nid == NID_id_PACE_ECDH_GM_AES_CBC_CMAC_128
524
0
                || nid == NID_id_PACE_ECDH_GM_AES_CBC_CMAC_192
525
0
                || nid == NID_id_PACE_ECDH_GM_AES_CBC_CMAC_256
526
0
                || nid == NID_id_PACE_ECDH_IM_AES_CBC_CMAC_128
527
0
                || nid == NID_id_PACE_ECDH_IM_AES_CBC_CMAC_192
528
0
                || nid == NID_id_PACE_ECDH_IM_AES_CBC_CMAC_256) {
529
            /* PACEInfo */
530
0
            check(d2i_PACE_INFO(&tmp_info, &in, info_len),
531
0
                    "Could not decode PACE info");
532
533
            /* lookup or create a pace context */
534
0
            get_ctx_by_keyID(pace_ctx, ctx->pace_ctxs, tmp_info->keyID, PACE_CTX);
535
0
            if (!pace_ctx) {
536
0
                goto err;
537
0
            }
538
539
0
            pace_ctx->version = (unsigned char) ASN1_INTEGER_get(tmp_info->version);
540
0
            if (pace_ctx->version <= 0 || pace_ctx->version > 2)
541
0
                goto err;
542
543
0
            if (!PACE_CTX_set_protocol(pace_ctx,
544
0
                        OBJ_obj2nid(tmp_info->protocol), ctx->tr_version))
545
0
                goto err;
546
547
0
        } else if (nid == NID_id_PACE_ECDH_GM
548
0
                || nid == NID_id_PACE_ECDH_IM
549
0
                || nid == NID_id_PACE_DH_GM
550
0
                || nid == NID_id_PACE_DH_IM) {
551
            /* PACEDomainParameterInfo */
552
0
            has_no_pace_dp_info = 0;
553
0
            check(d2i_PACE_DP_INFO(&tmp_dp_info, &in, info_len),
554
0
                    "Could not decode PACE domain parameter information");
555
556
            /* lookup or create a pace context */
557
0
            get_ctx_by_keyID(pace_ctx, ctx->pace_ctxs, tmp_dp_info->keyID, PACE_CTX);
558
0
            if (!pace_ctx) {
559
0
                goto err;
560
0
            }
561
562
0
            if (!aid2pkey(&ctx->pace_ctx->static_key, tmp_dp_info->aid, ctx->bn_ctx))
563
0
                goto err;
564
565
0
        } else if (nid == NID_id_TA) {
566
            /* TAInfo */
567
0
            check(d2i_TA_INFO(&tmp_ta_info, &in, info_len),
568
0
                    "Could not decode TA info");
569
570
0
            ctx->ta_ctx->version = (unsigned char) ASN1_INTEGER_get(tmp_ta_info->version);
571
0
            if (ctx->ta_ctx->version <= 0 || ctx->ta_ctx->version > 2)
572
0
                goto err;
573
            /* OID in TAInfo is less specific than the one in the certificate
574
             * Therefore this OID will be overwritten when we import a certificate
575
             * later on.*/
576
0
            ctx->ta_ctx->protocol = OBJ_obj2nid(tmp_ta_info->protocol);
577
0
        } else if (nid == NID_id_CA_DH_3DES_CBC_CBC
578
0
                || nid == NID_id_CA_DH_AES_CBC_CMAC_128
579
0
                || nid == NID_id_CA_DH_AES_CBC_CMAC_192
580
0
                || nid == NID_id_CA_DH_AES_CBC_CMAC_256
581
0
                || nid == NID_id_CA_ECDH_3DES_CBC_CBC
582
0
                || nid == NID_id_CA_ECDH_AES_CBC_CMAC_128
583
0
                || nid == NID_id_CA_ECDH_AES_CBC_CMAC_192
584
0
                || nid == NID_id_CA_ECDH_AES_CBC_CMAC_256) {
585
            /* CAInfo */
586
0
            check(d2i_CA_INFO(&tmp_ca_info, &in, info_len),
587
0
                    "Could not decode CA info");
588
589
            /* lookup or create a ca context */
590
0
            get_ctx_by_keyID(ca_ctx, ctx->ca_ctxs, tmp_ca_info->keyID, CA_CTX);
591
0
            if (!ca_ctx) {
592
0
                goto err;
593
0
            }
594
595
0
            ca_ctx->version = (unsigned char) ASN1_INTEGER_get(tmp_ca_info->version);
596
0
            if (ca_ctx->version <= 0 || ca_ctx->version > 3
597
0
                    || !CA_CTX_set_protocol(ca_ctx, nid))
598
0
                goto err;
599
600
0
        } else if (nid == NID_id_CA_DH
601
0
                || nid == NID_id_CA_ECDH) {
602
            /* ChipAuthenticationDomainParameterInfo */
603
0
            check(d2i_CA_DP_INFO(&tmp_ca_dp_info, &in, info_len),
604
0
                    "Could not decode CA domain parameter info");
605
606
            /* lookup or create a ca context */
607
0
            get_ctx_by_keyID(ca_ctx, ctx->ca_ctxs, tmp_ca_dp_info->keyID, CA_CTX);
608
0
            if (!ca_ctx) {
609
0
                goto err;
610
0
            }
611
612
0
            if (!aid2pkey(&ca_ctx->ka_ctx->key, tmp_ca_dp_info->aid, ctx->bn_ctx))
613
0
                goto err;
614
615
0
        } else if (nid == NID_id_PK_DH
616
0
                || nid == NID_id_PK_ECDH) {
617
            /* ChipAuthenticationPublicKeyInfo */
618
0
            check(d2i_CA_PUBLIC_KEY_INFO(&ca_public_key_info, &in, info_len),
619
0
                    "Could not decode CA PK domain parameter info");
620
621
            /* lookup or create a ca context */
622
0
            if (!tmp_ca_info) {
623
0
                goto err;
624
0
            }
625
0
            get_ctx_by_keyID(ca_ctx, ctx->ca_ctxs, tmp_ca_info->keyID, CA_CTX);
626
0
            if (!ca_ctx) {
627
0
                goto err;
628
0
            }
629
630
0
            if (!aid2pkey(&ca_ctx->ka_ctx->key,
631
0
                        ca_public_key_info->chipAuthenticationPublicKeyInfo->algorithmIdentifier,
632
0
                        ctx->bn_ctx))
633
0
                goto err;
634
635
0
            if (nid == NID_id_PK_DH) {
636
                /* FIXME the public key for DH is actually an ASN.1
637
                 * UNSIGNED INTEGER, which is an ASN.1 INTEGER that is
638
                 * always positive. Parsing the unsigned integer should be
639
                 * done in EVP_PKEY_set_key. */
640
0
                const unsigned char *p = ASN1_STRING_get0_data(ca_public_key_info->chipAuthenticationPublicKeyInfo->subjectPublicKey);
641
0
                check(d2i_ASN1_UINTEGER(&i, &p,
642
0
                            ASN1_STRING_length(ca_public_key_info->chipAuthenticationPublicKeyInfo->subjectPublicKey)),
643
0
                        "Could not decode CA PK");
644
0
                pubkey = ASN1_STRING_get0_data(i);
645
0
                pubkey_len = ASN1_STRING_length(i);
646
0
            } else {
647
0
                pubkey = ASN1_STRING_get0_data(ca_public_key_info->chipAuthenticationPublicKeyInfo->subjectPublicKey);
648
0
                pubkey_len = ASN1_STRING_length(ca_public_key_info->chipAuthenticationPublicKeyInfo->subjectPublicKey);
649
0
            }
650
651
0
            if (!EVP_PKEY_set_keys(ca_ctx->ka_ctx->key, NULL, 0, pubkey, pubkey_len, ctx->bn_ctx))
652
0
                goto err;
653
654
0
        } else if (nid == NID_id_CI) {
655
            /* ChipIdentifer or cardInfoLocator */
656
0
        } else if (nid == NID_id_PT) {
657
0
        } else if (nid == NID_id_RI_DH_SHA_1
658
0
                || nid == NID_id_RI_DH_SHA_224
659
0
                || nid == NID_id_RI_DH_SHA_256
660
0
                || nid == NID_id_RI_DH_SHA_384
661
0
                || nid == NID_id_RI_DH_SHA_512
662
0
                || nid == NID_id_RI_ECDH_SHA_1
663
0
                || nid == NID_id_RI_ECDH_SHA_224
664
0
                || nid == NID_id_RI_ECDH_SHA_256
665
0
                || nid == NID_id_RI_ECDH_SHA_384
666
0
                || nid == NID_id_RI_ECDH_SHA_512) {
667
            /* RestrictedIdentificationInfo */
668
0
            check(d2i_RI_INFO(&tmp_ri_info, &in, info_len),
669
0
                    "Could not decode RI info");
670
671
            /* create a ri context */
672
0
            get_ctx_by_keyID(ri_ctx, ctx->ri_ctxs, NULL, RI_CTX);
673
0
            if (!ri_ctx) {
674
0
                goto err;
675
0
            }
676
677
0
            if (!RI_CTX_set_protocol(ri_ctx, nid))
678
0
                goto err;
679
680
0
        } else if (nid == NID_id_RI_DH
681
0
                || nid == NID_id_RI_ECDH) {
682
            /* RestrictedIdentificationDomainParameterInfo */
683
0
            check(d2i_RI_DP_INFO(&tmp_ri_dp_info, &in, info_len),
684
0
                    "Could not decode RI domain parameter info");
685
686
0
            _count = sk_num((_STACK*) ctx->ri_ctxs);
687
0
            for (_i = 0; _i < _count; _i++) {
688
0
                ri_ctx = sk_value((_STACK*) ctx->ri_ctxs, _i);
689
0
                if (!ri_ctx)
690
0
                    goto err;
691
0
                if (!aid2pkey(&ri_ctx->static_key, tmp_ri_dp_info->aid, ctx->bn_ctx))
692
0
                    goto err;
693
0
            }
694
695
0
        } else {
696
0
            OBJ_obj2txt(obj_txt, sizeof obj_txt, oid, 0);
697
0
            debug("Unknown Identifier (%s) for %s", OBJ_nid2sn(nid), obj_txt);
698
0
        }
699
700
        /* if we have created the first PACE context, use it as default */
701
0
        if (!ctx->pace_ctx)
702
0
            ctx->pace_ctx = pace_ctx;
703
        /* if we have created the first CA context, use it as default */
704
0
        if (!ctx->ca_ctx)
705
0
            ctx->ca_ctx = ca_ctx;
706
        /* if we have created the first RI context, use it as default */
707
0
        if (!ctx->ri_ctx)
708
0
            ctx->ri_ctx = ri_ctx;
709
710
0
        todo -= info_len;
711
0
        in = info_start+info_len;
712
0
    }
713
714
    /* although a PACEDomainParameterInfo MUST be present in every version of
715
     * BSI TR-03110, they are not included in the EAC worked Example. We
716
     * recognize this error and use the keyID as standardizedDomainParameter */
717
0
    if (ctx->pace_ctx && has_no_pace_dp_info) {
718
0
        if (!EVP_PKEY_set_std_dp(ctx->pace_ctx->static_key, ctx->pace_ctx->id))
719
0
            goto err;
720
0
    }
721
722
0
    r = 1;
723
724
0
err:
725
0
    if (oid)
726
0
        ASN1_OBJECT_free(oid);
727
0
    if (tmp_info)
728
0
        PACE_INFO_free(tmp_info);
729
0
    if (tmp_dp_info)
730
0
        PACE_DP_INFO_free(tmp_dp_info);
731
0
    if (tmp_ta_info)
732
0
        TA_INFO_free(tmp_ta_info);
733
0
    if (tmp_ca_info)
734
0
        CA_INFO_free(tmp_ca_info);
735
0
    if (tmp_ri_info)
736
0
        RI_INFO_free(tmp_ri_info);
737
0
    if (tmp_ri_dp_info)
738
0
        RI_DP_INFO_free(tmp_ri_dp_info);
739
0
    if (i)
740
0
        ASN1_INTEGER_free(i);
741
0
    if (tmp_ca_dp_info)
742
0
        CA_DP_INFO_free(tmp_ca_dp_info);
743
0
    if (ca_public_key_info)
744
0
        CA_PUBLIC_KEY_INFO_free(ca_public_key_info);
745
746
0
    return r;
747
0
}
748
749
BUF_MEM *
750
asn1_pubkey(int protocol, EVP_PKEY *key, BN_CTX *bn_ctx, enum eac_tr_version tr_version)
751
0
{
752
0
    CVC_PUBKEY *eac_pubkey = NULL;
753
0
    BUF_MEM *pubkey = NULL;
754
0
    int l;
755
756
0
    eac_pubkey = CVC_pkey2pubkey(tr_version == EAC_TR_VERSION_2_01 ? 1 : 0, protocol, key, bn_ctx, NULL);
757
0
    if (!eac_pubkey)
758
0
        goto err;
759
760
0
    pubkey = BUF_MEM_new();
761
0
    if (!pubkey)
762
0
        goto err;
763
764
0
    l = i2d_CVC_PUBKEY(eac_pubkey, (unsigned char **) &pubkey->data);
765
0
    if (l < 0) {
766
0
        BUF_MEM_free(pubkey);
767
0
        pubkey = NULL;
768
0
        goto err;
769
0
    }
770
0
    pubkey->length = l;
771
0
    pubkey->max = l;
772
773
0
err:
774
0
    if (eac_pubkey)
775
0
        CVC_PUBKEY_free(eac_pubkey);
776
777
0
    return pubkey;
778
0
}