Coverage Report

Created: 2025-08-26 06:43

/src/opensc/src/libopensc/pkcs15-cert.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * pkcs15-cert.c: PKCS #15 certificate functions
3
 *
4
 * Copyright (C) 2001, 2002  Juha Yrjölä <juha.yrjola@iki.fi>
5
 *
6
 * This library is free software; you can redistribute it and/or
7
 * modify it under the terms of the GNU Lesser General Public
8
 * License as published by the Free Software Foundation; either
9
 * version 2.1 of the License, or (at your option) any later version.
10
 *
11
 * This library is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14
 * Lesser General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Lesser General Public
17
 * License along with this library; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19
 */
20
21
#ifdef HAVE_CONFIG_H
22
#include "config.h"
23
#endif
24
25
#include <stdlib.h>
26
#include <string.h>
27
#include <stdio.h>
28
#include <sys/stat.h>
29
#ifdef HAVE_UNISTD_H
30
#include <unistd.h>
31
#endif
32
#include <assert.h>
33
34
#include "internal.h"
35
#include "asn1.h"
36
#include "pkcs15.h"
37
38
static int
39
parse_x509_cert(sc_context_t *ctx, struct sc_pkcs15_der *der, struct sc_pkcs15_cert *cert)
40
0
{
41
0
  int r;
42
0
  struct sc_algorithm_id sig_alg = {0};
43
0
  struct sc_pkcs15_pubkey *pubkey = NULL;
44
0
  unsigned char *serial = NULL, *issuer = NULL, *subject = NULL, *buf =  der->value;
45
0
  size_t serial_len = 0, issuer_len = 0, subject_len = 0, data_len = 0, buflen = der->len;
46
0
  struct sc_asn1_entry asn1_version[] = {
47
0
    { "version", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, 0, &cert->version, NULL },
48
0
    { NULL, 0, 0, 0, NULL, NULL }
49
0
  };
50
0
  struct sc_asn1_entry asn1_extensions[] = {
51
0
    { "x509v3",   SC_ASN1_OCTET_STRING,    SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL| SC_ASN1_ALLOC, &cert->extensions, &cert->extensions_len },
52
0
    { NULL, 0, 0, 0, NULL, NULL }
53
0
  };
54
0
  struct sc_asn1_entry asn1_tbscert[] = {
55
0
    { "version",    SC_ASN1_STRUCT,    SC_ASN1_CTX | 0 | SC_ASN1_CONS, SC_ASN1_OPTIONAL, asn1_version, NULL },
56
0
    { "serialNumber", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_INTEGER, SC_ASN1_ALLOC, &serial, &serial_len },
57
0
    { "signature",    SC_ASN1_STRUCT,    SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL },
58
0
    { "issuer",   SC_ASN1_OCTET_STRING, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_ALLOC, &issuer, &issuer_len },
59
0
    { "validity",   SC_ASN1_STRUCT,    SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL },
60
0
    { "subject",    SC_ASN1_OCTET_STRING, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_ALLOC, &subject, &subject_len },
61
    /* Use a callback to get the algorithm, parameters and pubkey into sc_pkcs15_pubkey */
62
0
    { "subjectPublicKeyInfo",SC_ASN1_CALLBACK, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, sc_pkcs15_pubkey_from_spki_fields,  &pubkey },
63
0
    { "extensions",   SC_ASN1_STRUCT,    SC_ASN1_CTX | 3 | SC_ASN1_CONS, SC_ASN1_OPTIONAL, asn1_extensions, NULL },
64
0
    { NULL, 0, 0, 0, NULL, NULL }
65
0
  };
66
0
  struct sc_asn1_entry asn1_cert[] = {
67
0
    { "tbsCertificate", SC_ASN1_STRUCT,    SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, asn1_tbscert, NULL },
68
0
    { "signatureAlgorithm", SC_ASN1_ALGORITHM_ID, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, &sig_alg, NULL },
69
0
    { "signatureValue", SC_ASN1_BIT_STRING, SC_ASN1_TAG_BIT_STRING, 0, NULL, NULL },
70
0
    { NULL, 0, 0, 0, NULL, NULL }
71
0
  };
72
0
  struct sc_asn1_entry asn1_serial_number[] = {
73
0
    { "serialNumber", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_INTEGER, SC_ASN1_ALLOC, NULL, NULL },
74
0
    { NULL, 0, 0, 0, NULL, NULL }
75
0
  };
76
0
  struct sc_asn1_entry asn1_subject[] = {
77
0
    { "subject", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_ALLOC, NULL, NULL },
78
0
    { NULL, 0, 0, 0, NULL, NULL }
79
0
  };
80
0
  struct sc_asn1_entry asn1_issuer[] = {
81
0
    { "issuer", SC_ASN1_OCTET_STRING, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_ALLOC, NULL, NULL },
82
0
    { NULL, 0, 0, 0, NULL, NULL }
83
0
  };
84
85
0
  const u8 *obj;
86
0
  size_t objlen;
87
88
0
  LOG_FUNC_CALLED(ctx);
89
90
0
  memset(cert, 0, sizeof(*cert));
91
0
  obj = sc_asn1_verify_tag(ctx, buf, buflen, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, &objlen);
92
0
  if (obj == NULL)
93
0
    LOG_TEST_RET(ctx, SC_ERROR_INVALID_ASN1_OBJECT, "X.509 certificate not found");
94
95
0
  data_len = objlen + (obj - buf);
96
0
  cert->data.value = malloc(data_len);
97
0
  if (!cert->data.value)
98
0
    LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
99
0
  memcpy(cert->data.value, buf, data_len);
100
0
  cert->data.len = data_len;
101
102
0
  r = sc_asn1_decode(ctx, asn1_cert, obj, objlen, NULL, NULL);
103
0
  cert->key = pubkey;
104
0
  cert->version++;
105
106
0
  LOG_TEST_GOTO_ERR(ctx, r, "ASN.1 parsing of certificate failed");
107
108
0
  if (!pubkey)
109
0
    LOG_TEST_GOTO_ERR(ctx, SC_ERROR_INVALID_ASN1_OBJECT, "Unable to decode subjectPublicKeyInfo from cert");
110
111
112
0
  if (serial && serial_len)   {
113
0
    sc_format_asn1_entry(asn1_serial_number + 0, serial, &serial_len, 1);
114
0
    r = sc_asn1_encode(ctx, asn1_serial_number, &cert->serial, &cert->serial_len);
115
0
    LOG_TEST_GOTO_ERR(ctx, r, "ASN.1 encoding of serial failed");
116
0
  }
117
118
0
  if (subject && subject_len)   {
119
0
    sc_format_asn1_entry(asn1_subject + 0, subject, &subject_len, 1);
120
0
    r = sc_asn1_encode(ctx, asn1_subject, &cert->subject, &cert->subject_len);
121
0
    LOG_TEST_GOTO_ERR(ctx, r, "ASN.1 encoding of subject");
122
0
  }
123
124
0
  if (issuer && issuer_len)   {
125
0
    sc_format_asn1_entry(asn1_issuer + 0, issuer, &issuer_len, 1);
126
0
    r = sc_asn1_encode(ctx, asn1_issuer, &cert->issuer, &cert->issuer_len);
127
0
    LOG_TEST_GOTO_ERR(ctx, r, "ASN.1 encoding of issuer");
128
0
  }
129
130
0
err:
131
  /* not used for anything */
132
0
  sc_asn1_clear_algorithm_id(&sig_alg);
133
0
  free(serial);
134
0
  free(subject);
135
0
  free(issuer);
136
137
0
  LOG_FUNC_RETURN(ctx, r);
138
0
}
139
140
141
/* Get a component of Distinguished Name (e.i. subject or issuer) USING the oid tag.
142
 * dn can be either cert->subject or cert->issuer.
143
 * dn_len would be cert->subject_len or cert->issuer_len.
144
 *
145
 * Common types:
146
 *   CN:      struct sc_object_id type = {{2, 5, 4, 3, -1}};
147
 *   Country: struct sc_object_id type = {{2, 5, 4, 6, -1}};
148
 *   L:       struct sc_object_id type = {{2, 5, 4, 7, -1}};
149
 *   S:       struct sc_object_id type = {{2, 5, 4, 8, -1}};
150
 *   O:       struct sc_object_id type = {{2, 5, 4, 10, -1}};
151
 *   OU:      struct sc_object_id type = {{2, 5, 4, 11, -1}};
152
 *
153
 * if *name is NULL, sc_pkcs15_get_name_from_dn will allocate space for name.
154
 */
155
int
156
sc_pkcs15_get_name_from_dn(struct sc_context *ctx, const u8 *dn, size_t dn_len,
157
  const struct sc_object_id *type, u8 **name, size_t *name_len)
158
0
{
159
0
  const u8 *rdn = NULL;
160
0
  const u8 *next_ava = NULL;
161
0
  size_t rdn_len = 0;
162
0
  size_t next_ava_len = 0;
163
0
  int rv;
164
165
0
  rdn = sc_asn1_skip_tag(ctx, &dn, &dn_len, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, &rdn_len);
166
0
  if (rdn == NULL)
167
0
    LOG_TEST_RET(ctx, SC_ERROR_INVALID_ASN1_OBJECT, "ASN.1 decoding of Distinguished Name");
168
169
0
  for (next_ava = rdn, next_ava_len = rdn_len; next_ava_len; ) {
170
0
    const u8 *ava, *dummy, *oidp;
171
0
    struct sc_object_id oid;
172
0
    size_t ava_len = 0, dummy_len, oid_len = 0;
173
174
    /* unwrap the set and point to the next ava */
175
0
    ava = sc_asn1_skip_tag(ctx, &next_ava, &next_ava_len, SC_ASN1_TAG_SET | SC_ASN1_CONS, &ava_len);
176
0
    if (ava == NULL)
177
0
      LOG_TEST_RET(ctx, SC_ERROR_INVALID_ASN1_OBJECT, "ASN.1 decoding of AVA");
178
179
    /* It would be nice to use sc_asn1_decode here to parse the entire AVA, but we are missing 1 critical
180
     *  function in the templates: the ability to accept any tag for value. This prevents us from just
181
     *  grabbing the value as is out of the template. AVA's can have tags of PRINTABLE_STRING,
182
     *  TELETEXSTRING, T61STRING or UTF8_STRING with PRINTABLE_STRING and UTF8_STRING being the most common.
183
     * The other feature that would be nice is returning a pointer to our requested data using the space
184
     *  of the parent (basically what this code is doing here), rather than allocating and copying.
185
     */
186
187
    /* unwrap the sequence */
188
0
    dummy = ava; dummy_len = ava_len;
189
0
    ava = sc_asn1_skip_tag(ctx, &dummy, &dummy_len, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, &ava_len);
190
0
    if (ava == NULL)
191
0
      LOG_TEST_RET(ctx, SC_ERROR_INVALID_ASN1_OBJECT, "ASN.1 decoding of AVA");
192
193
    /* unwrap the oid */
194
0
    oidp = sc_asn1_skip_tag(ctx, &ava, &ava_len, SC_ASN1_TAG_OBJECT, &oid_len);
195
0
    if (ava == NULL)
196
0
      LOG_TEST_RET(ctx, SC_ERROR_INVALID_ASN1_OBJECT, "ASN.1 decoding of AVA OID");
197
198
    /* Convert to OID */
199
0
    rv = sc_asn1_decode_object_id(oidp, oid_len, &oid);
200
0
    if (rv != SC_SUCCESS)
201
0
      LOG_TEST_RET(ctx, SC_ERROR_INVALID_ASN1_OBJECT, "ASN.1 decoding of AVA OID");
202
203
0
    if (sc_compare_oid(&oid, type) == 0)
204
0
      continue;
205
206
    /* Yes, then return the name */
207
0
    dummy = sc_asn1_skip_tag(ctx, &ava, &ava_len, ava[0] & SC_ASN1_TAG_PRIMITIVE, &dummy_len);
208
0
    if (dummy == NULL)
209
0
      LOG_TEST_RET(ctx, SC_ERROR_INVALID_ASN1_OBJECT, "ASN.1 decoding of AVA name");
210
0
    if (*name == NULL) {
211
0
      *name = malloc(dummy_len);
212
0
      if (*name == NULL)
213
0
        LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
214
0
      *name_len = dummy_len;
215
0
    }
216
217
0
    *name_len = MIN(dummy_len, *name_len);
218
0
    memcpy(*name, dummy, *name_len);
219
0
    LOG_FUNC_RETURN(ctx, SC_SUCCESS);
220
0
  }
221
222
0
  LOG_FUNC_RETURN(ctx, SC_ERROR_ASN1_OBJECT_NOT_FOUND);
223
0
}
224
225
226
/* Get a specific extension from the cert.
227
 * The extension is identified by it's oid value.
228
 * NOTE: extensions can occur in any number or any order, which is why we
229
 *  can't parse them with a single pass of the asn1 decoder.
230
 * If is_critical is supplied, then it is set to 1 if the extension is critical
231
 * and 0 if it is not.
232
 * The data in the extension is extension specific.
233
 * The following are common extension values:
234
 *   Subject Key ID:    struct sc_object_id type = {{2, 5, 29, 14, -1}};
235
 *   Key Usage:     struct sc_object_id type = {{2, 5, 29, 15, -1}};
236
 *   Subject Alt Name:    struct sc_object_id type = {{2, 5, 29, 17, -1}};
237
 *   Basic Constraints:   struct sc_object_id type = {{2, 5, 29, 19, -1}};
238
 *   CRL Distribution Points: struct sc_object_id type = {{2, 5, 29, 31, -1}};
239
 *   Certificate Policies:  struct sc_object_id type = {{2, 5, 29, 32, -1}};
240
 *   Extended Key Usage:  struct sc_object_id type = {{2, 5, 29, 37, -1}};
241
 *
242
 * if *ext_val is NULL, sc_pkcs15_get_extension will allocate space for ext_val.
243
 */
244
int
245
sc_pkcs15_get_extension(struct sc_context *ctx, struct sc_pkcs15_cert *cert,
246
  const struct sc_object_id *type, u8 **ext_val,
247
  size_t *ext_val_len, int *is_critical)
248
0
{
249
0
  const u8 *ext = NULL;
250
0
  const u8 *next_ext = NULL;
251
0
  size_t ext_len = 0;
252
0
  size_t next_ext_len = 0;
253
0
  struct sc_object_id oid;
254
0
  u8 *val = NULL;
255
0
  size_t val_len = 0;
256
0
  int critical;
257
0
  int r;
258
0
  struct sc_asn1_entry asn1_cert_ext[] = {
259
0
    { "x509v3 entry OID", SC_ASN1_OBJECT, SC_ASN1_TAG_OBJECT, 0, &oid, 0 },
260
0
    { "criticalFlag",  SC_ASN1_BOOLEAN, SC_ASN1_TAG_BOOLEAN, SC_ASN1_OPTIONAL, &critical, NULL },
261
0
    { "extensionValue",SC_ASN1_OCTET_STRING, SC_ASN1_TAG_OCTET_STRING, SC_ASN1_ALLOC, &val, &val_len },
262
0
    { NULL, 0, 0, 0, NULL, NULL }
263
0
  };
264
265
0
  LOG_FUNC_CALLED(ctx);
266
267
0
  for (next_ext = cert->extensions, next_ext_len = cert->extensions_len; next_ext_len; ) {
268
    /* unwrap the set and point to the next ava */
269
0
    ext = sc_asn1_skip_tag(ctx, &next_ext, &next_ext_len,
270
0
      SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, &ext_len);
271
0
    if (ext == NULL)
272
0
      LOG_TEST_RET(ctx, SC_ERROR_INVALID_ASN1_OBJECT, "ASN.1 decoding of AVA");
273
274
    /*
275
     * use the sc_asn1_decoder for clarity. NOTE it would be more efficient to do this by hand
276
     * so we avoid the many malloc/frees here, but one hopes that one day the asn1_decode will allow
277
     * a 'static pointer' flag that returns a const pointer to the actual asn1 space so we only need
278
     * to make a final copy of the extension value before we return */
279
0
    critical = 0;
280
0
    r = sc_asn1_decode(ctx, asn1_cert_ext, ext, ext_len, NULL, NULL);
281
0
    if (r < 0)
282
0
      LOG_FUNC_RETURN(ctx, r);
283
284
    /* is it the RN we are looking for */
285
0
    if (sc_compare_oid(&oid, type) != 0) {
286
0
      if (*ext_val == NULL) {
287
0
        *ext_val = val;
288
0
        val = NULL;
289
0
        *ext_val_len = val_len;
290
        /* do not free here -- return the allocated value to caller */
291
0
      }
292
0
      else {
293
0
        *ext_val_len = MIN(*ext_val_len, val_len);
294
0
        if (val) {
295
0
          memcpy(*ext_val, val, *ext_val_len);
296
0
          free(val);
297
0
        }
298
0
      }
299
300
0
      if (is_critical)
301
0
        *is_critical = critical;
302
303
0
      r = (int)val_len;
304
0
      LOG_FUNC_RETURN(ctx, r);
305
0
    }
306
0
    if (val) {
307
0
      free(val);
308
0
      val = NULL;
309
0
    }
310
0
  }
311
0
  if (val)
312
0
      free(val);
313
314
0
  LOG_FUNC_RETURN(ctx, SC_ERROR_ASN1_OBJECT_NOT_FOUND);
315
0
}
316
317
/*
318
 *  Get an extension whose value is a bit string. These include keyUsage and extendedKeyUsage.
319
 *  See above for the other parameters.
320
 */
321
int
322
sc_pkcs15_get_bitstring_extension(struct sc_context *ctx,
323
  struct sc_pkcs15_cert *cert, const struct sc_object_id *type,
324
  unsigned int *value, int *is_critical)
325
0
{
326
0
  int r;
327
0
  u8 *bit_string = NULL;
328
0
  size_t bit_string_len=0, val_len = sizeof(*value);
329
0
  struct sc_asn1_entry asn1_bit_string[] = {
330
0
    { "bitString", SC_ASN1_BIT_FIELD, SC_ASN1_TAG_BIT_STRING, 0, value, &val_len },
331
0
    { NULL, 0, 0, 0, NULL, NULL }
332
0
  };
333
334
0
  LOG_FUNC_CALLED(ctx);
335
336
0
  r = sc_pkcs15_get_extension(ctx, cert, type, &bit_string, &bit_string_len, is_critical);
337
0
  LOG_TEST_RET(ctx, r, "Get extension error");
338
339
0
  r = sc_asn1_decode(ctx, asn1_bit_string, bit_string, bit_string_len, NULL, NULL);
340
0
  free(bit_string);
341
0
  LOG_TEST_RET(ctx, r, "Decoding extension bit string");
342
343
0
  LOG_FUNC_RETURN(ctx, SC_SUCCESS);
344
0
}
345
346
347
int
348
sc_pkcs15_pubkey_from_cert(struct sc_context *ctx,
349
    struct sc_pkcs15_der *cert_blob, struct sc_pkcs15_pubkey **out)
350
0
{
351
0
  int rv;
352
0
  struct sc_pkcs15_cert * cert;
353
354
0
  cert =  calloc(1, sizeof(struct sc_pkcs15_cert));
355
0
  if (cert == NULL)
356
0
    return SC_ERROR_OUT_OF_MEMORY;
357
358
0
  rv = parse_x509_cert(ctx, cert_blob, cert);
359
360
0
  *out = cert->key;
361
0
  cert->key = NULL;
362
0
  sc_pkcs15_free_certificate(cert);
363
364
0
  LOG_FUNC_RETURN(ctx, rv);
365
0
}
366
367
368
int
369
sc_pkcs15_read_certificate(struct sc_pkcs15_card *p15card, const struct sc_pkcs15_cert_info *info,
370
    int private_obj, struct sc_pkcs15_cert **cert_out)
371
0
{
372
0
  struct sc_context *ctx = NULL;
373
0
  struct sc_pkcs15_cert *cert = NULL;
374
0
  struct sc_pkcs15_der der;
375
0
  int r;
376
377
0
  if (p15card == NULL || info == NULL || cert_out == NULL) {
378
0
    return SC_ERROR_INVALID_ARGUMENTS;
379
0
  }
380
0
  ctx = p15card->card->ctx;
381
0
  LOG_FUNC_CALLED(ctx);
382
383
0
  if (info->value.len && info->value.value)   {
384
0
    sc_der_copy(&der, &info->value);
385
0
  }
386
0
  else if (info->path.len) {
387
0
    r = sc_pkcs15_read_file(p15card, &info->path, &der.value, &der.len, private_obj);
388
0
    LOG_TEST_RET(ctx, r, "Unable to read certificate file.");
389
0
  }
390
0
  else   {
391
0
    LOG_FUNC_RETURN(ctx, SC_ERROR_OBJECT_NOT_FOUND);
392
0
  }
393
394
0
  cert = malloc(sizeof(struct sc_pkcs15_cert));
395
0
  if (cert == NULL) {
396
0
    free(der.value);
397
0
    LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
398
0
  }
399
0
  memset(cert, 0, sizeof(struct sc_pkcs15_cert));
400
0
  if (parse_x509_cert(ctx, &der, cert)) {
401
0
    free(der.value);
402
0
    sc_pkcs15_free_certificate(cert);
403
0
    LOG_FUNC_RETURN(ctx, SC_ERROR_INVALID_ASN1_OBJECT);
404
0
  }
405
0
  free(der.value);
406
407
0
  *cert_out = cert;
408
0
  LOG_FUNC_RETURN(ctx, SC_SUCCESS);
409
0
}
410
411
412
static const struct sc_asn1_entry c_asn1_cred_ident[] = {
413
  { "idType", SC_ASN1_INTEGER,      SC_ASN1_TAG_INTEGER, 0, NULL, NULL },
414
  { "idValue",  SC_ASN1_OCTET_STRING, SC_ASN1_TAG_OCTET_STRING, 0, NULL, NULL },
415
  { NULL, 0, 0, 0, NULL, NULL }
416
};
417
static const struct sc_asn1_entry c_asn1_com_cert_attr[] = {
418
  { "iD",   SC_ASN1_PKCS15_ID, SC_ASN1_TAG_OCTET_STRING, 0, NULL, NULL },
419
  { "authority",  SC_ASN1_BOOLEAN,   SC_ASN1_TAG_BOOLEAN, SC_ASN1_OPTIONAL, NULL, NULL },
420
  { "identifier", SC_ASN1_STRUCT,    SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
421
  /* FIXME: Add rest of the optional fields */
422
  { NULL, 0, 0, 0, NULL, NULL }
423
};
424
static const struct sc_asn1_entry c_asn1_x509_cert_value_choice[] = {
425
  { "path", SC_ASN1_PATH,    SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
426
  { "direct", SC_ASN1_OCTET_STRING, SC_ASN1_CTX | 0 | SC_ASN1_CONS, SC_ASN1_OPTIONAL | SC_ASN1_ALLOC, NULL, NULL },
427
  { NULL, 0, 0, 0, NULL, NULL }
428
};
429
static const struct sc_asn1_entry c_asn1_x509_cert_attr[] = {
430
  { "value",  SC_ASN1_CHOICE, 0, 0, NULL, NULL },
431
  { NULL, 0, 0, 0, NULL, NULL }
432
};
433
static const struct sc_asn1_entry c_asn1_type_cert_attr[] = {
434
  { "x509CertificateAttributes", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL },
435
  { NULL, 0, 0, 0, NULL, NULL }
436
};
437
static const struct sc_asn1_entry c_asn1_cert[] = {
438
  { "x509Certificate", SC_ASN1_PKCS15_OBJECT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL },
439
  { NULL, 0, 0, 0, NULL, NULL }
440
};
441
442
443
int
444
sc_pkcs15_decode_cdf_entry(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *obj,
445
    const u8 ** buf, size_t *buflen)
446
0
{
447
0
  sc_context_t *ctx = p15card->card->ctx;
448
0
  struct sc_pkcs15_cert_info info;
449
0
  struct sc_asn1_entry  asn1_cred_ident[3], asn1_com_cert_attr[4],
450
0
        asn1_x509_cert_attr[2], asn1_type_cert_attr[2],
451
0
        asn1_cert[2], asn1_x509_cert_value_choice[3];
452
0
  struct sc_asn1_pkcs15_object cert_obj = {
453
0
    obj, asn1_com_cert_attr, NULL,
454
0
    asn1_type_cert_attr };
455
0
  sc_pkcs15_der_t *der = &info.value;
456
0
  u8 id_value[128];
457
0
  int id_type;
458
0
  size_t id_value_len = sizeof(id_value);
459
0
  int r;
460
461
0
  sc_copy_asn1_entry(c_asn1_cred_ident, asn1_cred_ident);
462
0
  sc_copy_asn1_entry(c_asn1_com_cert_attr, asn1_com_cert_attr);
463
0
  sc_copy_asn1_entry(c_asn1_x509_cert_attr, asn1_x509_cert_attr);
464
0
  sc_copy_asn1_entry(c_asn1_x509_cert_value_choice, asn1_x509_cert_value_choice);
465
0
  sc_copy_asn1_entry(c_asn1_type_cert_attr, asn1_type_cert_attr);
466
0
  sc_copy_asn1_entry(c_asn1_cert, asn1_cert);
467
468
0
  sc_format_asn1_entry(asn1_cred_ident + 0, &id_type, NULL, 0);
469
0
  sc_format_asn1_entry(asn1_cred_ident + 1, &id_value, &id_value_len, 0);
470
0
  sc_format_asn1_entry(asn1_com_cert_attr + 0, &info.id, NULL, 0);
471
0
  sc_format_asn1_entry(asn1_com_cert_attr + 1, &info.authority, NULL, 0);
472
0
  sc_format_asn1_entry(asn1_com_cert_attr + 2, asn1_cred_ident, NULL, 0);
473
0
  sc_format_asn1_entry(asn1_x509_cert_attr + 0, asn1_x509_cert_value_choice, NULL, 0);
474
0
  sc_format_asn1_entry(asn1_x509_cert_value_choice + 0, &info.path, NULL, 0);
475
0
  sc_format_asn1_entry(asn1_x509_cert_value_choice + 1, &der->value, &der->len, 0);
476
0
  sc_format_asn1_entry(asn1_type_cert_attr + 0, asn1_x509_cert_attr, NULL, 0);
477
0
  sc_format_asn1_entry(asn1_cert + 0, &cert_obj, NULL, 0);
478
479
  /* Fill in defaults */
480
0
  memset(&info, 0, sizeof(info));
481
0
  info.authority = 0;
482
483
0
  r = sc_asn1_decode(ctx, asn1_cert, *buf, *buflen, buf, buflen);
484
  /* In case of error, trash the cert value (direct coding) */
485
0
  if (r < 0 && der->value)
486
0
    free(der->value);
487
0
  if (r == SC_ERROR_ASN1_END_OF_CONTENTS)
488
0
    return r;
489
0
  LOG_TEST_RET(ctx, r, "ASN.1 decoding failed");
490
491
0
  if (!p15card->app || !p15card->app->ddo.aid.len) {
492
0
    if (!p15card->file_app) {
493
0
      free(der->value);
494
0
      return SC_ERROR_INTERNAL;
495
0
    }
496
0
    r = sc_pkcs15_make_absolute_path(&p15card->file_app->path, &info.path);
497
0
    LOG_TEST_RET(ctx, r, "Cannot make absolute path");
498
0
  }
499
0
  else   {
500
0
    info.path.aid = p15card->app->ddo.aid;
501
0
  }
502
0
  sc_log(ctx, "Certificate path '%s'", sc_print_path(&info.path));
503
504
0
  switch (p15card->opts.pin_protected_certificate) {
505
0
    case SC_PKCS15_CARD_OPTS_PRIV_CERT_DECLASSIFY:
506
0
      sc_log(ctx, "Declassifying certificate");
507
0
      obj->flags &= ~SC_PKCS15_CO_FLAG_PRIVATE;
508
0
      break;
509
0
    case SC_PKCS15_CARD_OPTS_PRIV_CERT_IGNORE:
510
0
      sc_log(ctx, "Ignoring certificate");
511
0
      free(der->value);
512
0
      return 0;
513
0
  }
514
515
0
  obj->type = SC_PKCS15_TYPE_CERT_X509;
516
0
  obj->data = malloc(sizeof(info));
517
0
  if (obj->data == NULL)
518
0
    LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
519
0
  memcpy(obj->data, &info, sizeof(info));
520
521
0
  return 0;
522
0
}
523
524
525
int
526
sc_pkcs15_encode_cdf_entry(sc_context_t *ctx, const struct sc_pkcs15_object *obj,
527
    u8 **buf, size_t *bufsize)
528
0
{
529
0
  struct sc_asn1_entry  asn1_cred_ident[3], asn1_com_cert_attr[4],
530
0
        asn1_x509_cert_attr[2], asn1_type_cert_attr[2],
531
0
        asn1_cert[2], asn1_x509_cert_value_choice[3];
532
0
  struct sc_pkcs15_cert_info *infop = (sc_pkcs15_cert_info_t *) obj->data;
533
0
  sc_pkcs15_der_t *der = &infop->value;
534
0
  struct sc_asn1_pkcs15_object cert_obj = { (struct sc_pkcs15_object *) obj,
535
0
              asn1_com_cert_attr, NULL,
536
0
              asn1_type_cert_attr };
537
0
  int r;
538
539
0
  sc_copy_asn1_entry(c_asn1_cred_ident, asn1_cred_ident);
540
0
  sc_copy_asn1_entry(c_asn1_com_cert_attr, asn1_com_cert_attr);
541
0
  sc_copy_asn1_entry(c_asn1_x509_cert_attr, asn1_x509_cert_attr);
542
0
  sc_copy_asn1_entry(c_asn1_x509_cert_value_choice, asn1_x509_cert_value_choice);
543
0
  sc_copy_asn1_entry(c_asn1_type_cert_attr, asn1_type_cert_attr);
544
0
  sc_copy_asn1_entry(c_asn1_cert, asn1_cert);
545
546
0
  sc_format_asn1_entry(asn1_com_cert_attr + 0, (void *) &infop->id, NULL, 1);
547
0
  if (infop->authority)
548
0
    sc_format_asn1_entry(asn1_com_cert_attr + 1, (void *) &infop->authority, NULL, 1);
549
0
  if (infop->path.len || !der->value) {
550
0
    sc_format_asn1_entry(asn1_x509_cert_value_choice + 0, &infop->path, NULL, 1);
551
0
  } else {
552
0
    sc_format_asn1_entry(asn1_x509_cert_value_choice + 1, der->value, &der->len, 1);
553
0
  }
554
0
  sc_format_asn1_entry(asn1_type_cert_attr + 0, &asn1_x509_cert_value_choice, NULL, 1);
555
0
  sc_format_asn1_entry(asn1_cert + 0, (void *) &cert_obj, NULL, 1);
556
557
0
  r = sc_asn1_encode(ctx, asn1_cert, buf, bufsize);
558
559
0
  return r;
560
0
}
561
562
/* Only certain usages are valid for a given algorithm, return all the usages
563
 * that the algorithm supports so we can use it as a filter for all
564
 * the public and private key usages
565
 */
566
static unsigned int
567
sc_pkcs15_alg_flags_from_algorithm(unsigned long algorithm)
568
0
{
569
0
  switch (algorithm) {
570
0
  case SC_ALGORITHM_RSA:
571
0
    return SC_PKCS15_PRKEY_USAGE_ENCRYPT | SC_PKCS15_PRKEY_USAGE_WRAP |
572
0
           SC_PKCS15_PRKEY_USAGE_VERIFY | SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER |
573
0
           SC_PKCS15_PRKEY_USAGE_DECRYPT | SC_PKCS15_PRKEY_USAGE_UNWRAP |
574
0
           SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_SIGNRECOVER |
575
0
           SC_PKCS15_PRKEY_USAGE_NONREPUDIATION;
576
#ifdef SC_ALGORITHM_DH
577
  case SC_ALGORITHM_DH:
578
    return SC_PKCS15_PRKEY_USAGE_DERIVE ;
579
#endif
580
0
  case SC_ALGORITHM_EC:
581
0
    return SC_PKCS15_PRKEY_USAGE_DERIVE | SC_PKCS15_PRKEY_USAGE_VERIFY|
582
0
           SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_NONREPUDIATION;
583
0
  case SC_ALGORITHM_GOSTR3410:
584
0
    return SC_PKCS15_PRKEY_USAGE_DERIVE | SC_PKCS15_PRKEY_USAGE_VERIFY|
585
0
           SC_PKCS15_PRKEY_USAGE_SIGN | SC_PKCS15_PRKEY_USAGE_NONREPUDIATION;
586
0
  }
587
0
  return 0;
588
0
}
589
590
/* These are the cert key usage bits that map to various PKCS #11 (and thus PKCS #15) flags */
591
#define SC_PKCS15_X509_USAGE_SIGNATURE \
592
0
  (SC_X509_DIGITAL_SIGNATURE | \
593
0
  SC_X509_NON_REPUDIATION    | \
594
0
  SC_X509_KEY_CERT_SIGN      | \
595
0
  SC_X509_CRL_SIGN)
596
#define SC_PKCS15_X509_USAGE_DERIVE \
597
0
  SC_X509_KEY_AGREEMENT
598
#define SC_PKCS15_X509_USAGE_UNWRAP \
599
0
  (SC_X509_KEY_ENCIPHERMENT | \
600
0
  SC_X509_KEY_AGREEMENT)
601
#define SC_PKCS15_X509_USAGE_DECRYPT \
602
0
  (SC_X509_DATA_ENCIPHERMENT | \
603
0
  SC_X509_ENCIPHER_ONLY)
604
#define SC_PKCS15_X509_USAGE_NONREPUDIATION \
605
0
  SC_X509_NON_REPUDIATION
606
607
/* map a cert usage and algorithm to public and private key usages */
608
int
609
sc_pkcs15_map_usage(unsigned int cert_usage, unsigned long algorithm,
610
  unsigned int *pub_usage_ptr, unsigned int *pr_usage_ptr,
611
  int allow_nonrepudiation)
612
0
{
613
0
  unsigned int pub_usage = 0, pr_usage = 0;
614
0
  unsigned int alg_flags = sc_pkcs15_alg_flags_from_algorithm(algorithm);
615
616
0
  if (cert_usage & SC_PKCS15_X509_USAGE_SIGNATURE) {
617
0
    pub_usage |= SC_PKCS15_PRKEY_USAGE_VERIFY|SC_PKCS15_PRKEY_USAGE_VERIFYRECOVER;
618
0
    pr_usage |= SC_PKCS15_PRKEY_USAGE_SIGN|SC_PKCS15_PRKEY_USAGE_SIGNRECOVER;
619
0
  }
620
0
  if (cert_usage & SC_PKCS15_X509_USAGE_DERIVE) {
621
0
    pub_usage |= SC_PKCS15_PRKEY_USAGE_DERIVE;
622
0
    pr_usage |= SC_PKCS15_PRKEY_USAGE_DERIVE;
623
0
  }
624
0
  if (cert_usage & (SC_PKCS15_X509_USAGE_DECRYPT|SC_PKCS15_X509_USAGE_UNWRAP)) {
625
0
    pub_usage |= SC_PKCS15_PRKEY_USAGE_ENCRYPT;
626
0
    pr_usage |= SC_PKCS15_PRKEY_USAGE_DECRYPT;
627
0
  }
628
0
  if (allow_nonrepudiation && (cert_usage & SC_PKCS15_X509_USAGE_NONREPUDIATION)) {
629
0
    pub_usage |= SC_PKCS15_PRKEY_USAGE_NONREPUDIATION;
630
0
    pr_usage |= SC_PKCS15_PRKEY_USAGE_NONREPUDIATION;
631
0
  }
632
  /* filter usages algorithm */
633
0
  if (pub_usage_ptr) {
634
0
    *pub_usage_ptr = pub_usage & alg_flags;
635
0
  }
636
0
  if (pr_usage_ptr) {
637
0
    *pr_usage_ptr = pr_usage & alg_flags;
638
0
  }
639
0
  return SC_SUCCESS;
640
0
}
641
642
void
643
sc_pkcs15_free_certificate(struct sc_pkcs15_cert *cert)
644
0
{
645
0
  if (cert == NULL) {
646
0
    return;
647
0
  }
648
649
0
  sc_pkcs15_free_pubkey(cert->key);
650
0
  free(cert->subject);
651
0
  free(cert->issuer);
652
0
  free(cert->serial);
653
0
  free(cert->data.value);
654
0
  free(cert->extensions);
655
0
  free(cert);
656
0
}
657
658
659
void
660
sc_pkcs15_free_cert_info(sc_pkcs15_cert_info_t *cert)
661
0
{
662
0
  if (!cert)
663
0
    return;
664
0
  free(cert->value.value);
665
0
  free(cert);
666
0
}