Coverage Report

Created: 2025-11-13 06:26

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/opensc/src/libopensc/pkcs15-skey.c
Line
Count
Source
1
/*
2
 * pkcs15-skey.c: PKCS #15 secret key functions
3
 *
4
 * Copyright (C) 2002  Juha Yrjölä <juha.yrjola@iki.fi>
5
 * Copyright (C) 2011  Viktor Tarasov <viktor.tarasov@opentrust.com>
6
 *
7
 * This library is free software; you can redistribute it and/or
8
 * modify it under the terms of the GNU Lesser General Public
9
 * License as published by the Free Software Foundation; either
10
 * version 2.1 of the License, or (at your option) any later version.
11
 *
12
 * This library is distributed in the hope that it will be useful,
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15
 * Lesser General Public License for more details.
16
 *
17
 * You should have received a copy of the GNU Lesser General Public
18
 * License along with this library; if not, write to the Free Software
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20
 */
21
#include "internal.h"
22
#include "pkcs15.h"
23
#include "pkcs11/pkcs11.h"
24
#include "asn1.h"
25
#include <stdlib.h>
26
#include <string.h>
27
#include <stdio.h>
28
#include <assert.h>
29
30
/*
31
 * in src/libopensc/types.h SC_MAX_SUPPORTED_ALGORITHMS  defined as 16
32
 */
33
0
#define C_ASN1_SUPPORTED_ALGORITHMS_SIZE (SC_MAX_SUPPORTED_ALGORITHMS + 1)
34
static const struct sc_asn1_entry c_asn1_supported_algorithms[C_ASN1_SUPPORTED_ALGORITHMS_SIZE] = {
35
  { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
36
  { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
37
  { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
38
  { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
39
  { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
40
  { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
41
  { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
42
  { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
43
  { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
44
  { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
45
  { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
46
  { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
47
  { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
48
  { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
49
  { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
50
  { "algorithmReference", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
51
  { NULL, 0, 0, 0, NULL, NULL }
52
};
53
54
#define C_ASN1_COM_KEY_ATTR_SIZE 7
55
static const struct sc_asn1_entry c_asn1_com_key_attr[C_ASN1_COM_KEY_ATTR_SIZE] = {
56
  { "iD",    SC_ASN1_PKCS15_ID, SC_ASN1_TAG_OCTET_STRING, 0, NULL, NULL},
57
  { "usage",   SC_ASN1_BIT_FIELD, SC_ASN1_TAG_BIT_STRING, 0, NULL, NULL},
58
  { "native",      SC_ASN1_BOOLEAN, SC_ASN1_TAG_BOOLEAN, SC_ASN1_OPTIONAL, NULL, NULL },
59
  { "accessFlags", SC_ASN1_BIT_FIELD, SC_ASN1_TAG_BIT_STRING, SC_ASN1_OPTIONAL, NULL, NULL},
60
  { "keyReference",SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL },
61
  { "algReference", SC_ASN1_STRUCT, SC_ASN1_CONS | SC_ASN1_CTX | 1, SC_ASN1_OPTIONAL, NULL, NULL },
62
  { NULL, 0, 0, 0, NULL, NULL }
63
};
64
65
#define C_ASN1_COM_SKEY_ATTR_SIZE 2
66
static const struct sc_asn1_entry c_asn1_com_skey_attr[C_ASN1_COM_SKEY_ATTR_SIZE] = {
67
  { "keyLen", SC_ASN1_INTEGER, SC_ASN1_TAG_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL},
68
  { NULL, 0, 0, 0, NULL, NULL }
69
};
70
71
#define C_ASN1_COM_SKEY_GENERIC_VALUE_ATTR_SIZE 2
72
static const struct sc_asn1_entry c_asn1_generic_skey_value_attr[C_ASN1_COM_SKEY_GENERIC_VALUE_ATTR_SIZE] = {
73
  { "path", SC_ASN1_PATH, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL},
74
  { NULL, 0, 0, 0, NULL, NULL }
75
};
76
77
#define C_ASN1_COM_SKEY_GENERIC_ATTR_SIZE 2
78
static const struct sc_asn1_entry c_asn1_generic_skey_attr[C_ASN1_COM_SKEY_GENERIC_ATTR_SIZE] = {
79
  { "secretKeyAttributes", SC_ASN1_STRUCT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, 0, NULL, NULL},
80
  { NULL, 0, 0, 0, NULL, NULL }
81
};
82
83
#define C_ASN1_SKEY_CHOICE_SIZE 5
84
static const struct sc_asn1_entry c_asn1_skey_choice[C_ASN1_SKEY_CHOICE_SIZE] = {
85
  { "genericSecretKey", SC_ASN1_PKCS15_OBJECT, SC_ASN1_TAG_SEQUENCE | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
86
  { "desKey", SC_ASN1_PKCS15_OBJECT, SC_ASN1_CTX | 2 | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
87
  { "des2Key",  SC_ASN1_PKCS15_OBJECT, SC_ASN1_CTX | 3 | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
88
  { "des3Key",  SC_ASN1_PKCS15_OBJECT, SC_ASN1_CTX | 4 | SC_ASN1_CONS, SC_ASN1_OPTIONAL, NULL, NULL },
89
  { NULL, 0, 0, 0, NULL, NULL }
90
};
91
92
#define C_ASN1_SKEY_SIZE 2
93
static const struct sc_asn1_entry c_asn1_skey[C_ASN1_SKEY_SIZE] = {
94
  { "secretKey",  SC_ASN1_CHOICE, 0, 0, NULL, NULL },
95
  { NULL, 0, 0, 0, NULL, NULL }
96
};
97
98
99
int
100
sc_pkcs15_decode_skdf_entry(struct sc_pkcs15_card *p15card, struct sc_pkcs15_object *obj,
101
    const u8 ** buf, size_t *buflen)
102
4.09k
{
103
4.09k
        struct sc_context *ctx = p15card->card->ctx;
104
4.09k
        struct sc_pkcs15_skey_info info;
105
4.09k
  int r, i, ii;
106
4.09k
  size_t usage_len = sizeof(info.usage);
107
4.09k
  size_t af_len = sizeof(info.access_flags);
108
4.09k
  struct sc_asn1_entry asn1_com_key_attr[C_ASN1_COM_KEY_ATTR_SIZE];
109
4.09k
  struct sc_asn1_entry asn1_com_skey_attr[C_ASN1_COM_SKEY_ATTR_SIZE];
110
4.09k
  struct sc_asn1_entry asn1_generic_skey_attr[C_ASN1_COM_SKEY_GENERIC_ATTR_SIZE];
111
4.09k
  struct sc_asn1_entry asn1_generic_skey_value_attr[C_ASN1_COM_SKEY_GENERIC_VALUE_ATTR_SIZE];
112
4.09k
  struct sc_asn1_entry asn1_skey_choice[C_ASN1_SKEY_CHOICE_SIZE];
113
4.09k
  struct sc_asn1_entry asn1_skey[C_ASN1_SKEY_SIZE];
114
4.09k
  struct sc_asn1_entry asn1_supported_algorithms[C_ASN1_SUPPORTED_ALGORITHMS_SIZE];
115
4.09k
  struct sc_asn1_pkcs15_object skey_des_obj = {
116
4.09k
    obj, asn1_com_key_attr, asn1_com_skey_attr, asn1_generic_skey_attr
117
4.09k
  };
118
4.09k
  static const struct sc_object_id id_aes = { { 2, 16, 840, 1, 101, 3, 4, 1, -1 } };
119
4.09k
  struct sc_object_id temp_oid;
120
121
4.09k
  SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_ASN1);
122
123
4.09k
  sc_copy_asn1_entry(c_asn1_skey, asn1_skey);
124
4.09k
  sc_copy_asn1_entry(c_asn1_skey_choice, asn1_skey_choice);
125
4.09k
  sc_copy_asn1_entry(c_asn1_supported_algorithms, asn1_supported_algorithms);
126
127
4.09k
  sc_copy_asn1_entry(c_asn1_com_key_attr, asn1_com_key_attr);
128
4.09k
  sc_copy_asn1_entry(c_asn1_com_skey_attr, asn1_com_skey_attr);
129
4.09k
  sc_copy_asn1_entry(c_asn1_generic_skey_attr, asn1_generic_skey_attr);
130
4.09k
  sc_copy_asn1_entry(c_asn1_generic_skey_value_attr, asn1_generic_skey_value_attr);
131
132
4.09k
  sc_format_asn1_entry(asn1_skey + 0, asn1_skey_choice, NULL, 0);
133
4.09k
  sc_format_asn1_entry(asn1_skey_choice + 0, &skey_des_obj, NULL, 0);
134
4.09k
  sc_format_asn1_entry(asn1_skey_choice + 1, &skey_des_obj, NULL, 0);
135
4.09k
  sc_format_asn1_entry(asn1_skey_choice + 2, &skey_des_obj, NULL, 0);
136
4.09k
  sc_format_asn1_entry(asn1_skey_choice + 3, &skey_des_obj, NULL, 0);
137
138
4.09k
  sc_format_asn1_entry(asn1_com_key_attr + 0, &info.id, NULL, 0);
139
4.09k
  sc_format_asn1_entry(asn1_com_key_attr + 1, &info.usage, &usage_len, 0);
140
4.09k
  sc_format_asn1_entry(asn1_com_key_attr + 2, &info.native, NULL, 0);
141
4.09k
  sc_format_asn1_entry(asn1_com_key_attr + 3, &info.access_flags, &af_len, 0);
142
4.09k
  sc_format_asn1_entry(asn1_com_key_attr + 4, &info.key_reference, NULL, 0);
143
69.6k
  for (i=0; i<SC_MAX_SUPPORTED_ALGORITHMS && (asn1_supported_algorithms + i)->name; i++)
144
65.5k
    sc_format_asn1_entry(asn1_supported_algorithms + i, &info.algo_refs[i], NULL, 0);
145
4.09k
  sc_format_asn1_entry(asn1_com_key_attr + 5, asn1_supported_algorithms, NULL, 0);
146
147
4.09k
  sc_format_asn1_entry(asn1_com_skey_attr + 0, &info.value_len, NULL, 0);
148
149
4.09k
  sc_format_asn1_entry(asn1_generic_skey_attr + 0, asn1_generic_skey_value_attr, NULL, 0);
150
4.09k
  sc_format_asn1_entry(asn1_generic_skey_value_attr + 0, &info.path, NULL, 0);
151
152
        /* Fill in defaults */
153
4.09k
  memset(&info, 0, sizeof(info));
154
4.09k
  info.native = 1;
155
156
4.09k
  r = sc_asn1_decode(ctx, asn1_skey, *buf, *buflen, buf, buflen);
157
4.09k
  if (r == SC_ERROR_ASN1_END_OF_CONTENTS)
158
998
    return r;
159
3.10k
  LOG_TEST_RET(ctx, r, "ASN.1 decoding failed");
160
84
  if (asn1_skey_choice[0].flags & SC_ASN1_PRESENT) {
161
72
    obj->type = SC_PKCS15_TYPE_SKEY_GENERIC;
162
163
    /* Check key type. framework-pkcs15 recognizes one type per key, and AES is the only algorithm supported for
164
    * SKEY_GENERIC type keys, so just check if this key is AES compatible. */
165
166
110
    for (i = 0; i < SC_MAX_SUPPORTED_ALGORITHMS && info.algo_refs[i] != 0 && info.key_type == 0; i++) {
167
646
      for (ii = 0; ii < SC_MAX_SUPPORTED_ALGORITHMS && p15card->tokeninfo != 0; ii++) {
168
608
        if (info.algo_refs[i] == p15card->tokeninfo->supported_algos[ii].reference) {
169
0
          temp_oid = p15card->tokeninfo->supported_algos[ii].algo_id;
170
0
          temp_oid.value[8] = -1; /* strip off AES subtype octet*/
171
172
0
          if (sc_compare_oid(&id_aes, &temp_oid)) {
173
0
            info.key_type = CKK_AES;
174
0
            break;
175
0
          }
176
0
        }
177
608
      }
178
38
    }
179
72
  }
180
12
  else if (asn1_skey_choice[1].flags & SC_ASN1_PRESENT)
181
1
    obj->type = SC_PKCS15_TYPE_SKEY_DES;
182
11
  else if (asn1_skey_choice[2].flags & SC_ASN1_PRESENT)
183
1
    obj->type = SC_PKCS15_TYPE_SKEY_2DES;
184
10
  else if (asn1_skey_choice[3].flags & SC_ASN1_PRESENT)
185
10
    obj->type = SC_PKCS15_TYPE_SKEY_3DES;
186
0
  else
187
0
    LOG_TEST_RET(ctx, SC_ERROR_NOT_SUPPORTED, "unsupported secret key type");
188
189
84
  obj->data = malloc(sizeof(info));
190
84
  if (obj->data == NULL)
191
84
    LOG_FUNC_RETURN(ctx, SC_ERROR_OUT_OF_MEMORY);
192
84
  memcpy(obj->data, &info, sizeof(info));
193
194
84
  LOG_FUNC_RETURN(ctx, SC_SUCCESS);
195
84
}
196
197
198
int sc_pkcs15_encode_skdf_entry(struct sc_context *ctx,
199
         const struct sc_pkcs15_object *obj,
200
         u8 **buf, size_t *buflen)
201
0
{
202
0
  struct sc_pkcs15_skey_info *skey = (struct sc_pkcs15_skey_info *) obj->data;
203
0
  int r, i;
204
0
  size_t usage_len = sizeof(skey->usage);
205
0
  size_t af_len = sizeof(skey->access_flags);
206
0
  struct sc_asn1_entry asn1_com_key_attr[C_ASN1_COM_KEY_ATTR_SIZE];
207
0
  struct sc_asn1_entry asn1_com_skey_attr[C_ASN1_COM_SKEY_ATTR_SIZE];
208
0
  struct sc_asn1_entry asn1_generic_skey_attr[C_ASN1_COM_SKEY_GENERIC_ATTR_SIZE];
209
0
  struct sc_asn1_entry asn1_generic_skey_value_attr[C_ASN1_COM_SKEY_GENERIC_VALUE_ATTR_SIZE];
210
0
  struct sc_asn1_entry asn1_skey_choice[C_ASN1_SKEY_CHOICE_SIZE];
211
0
  struct sc_asn1_entry asn1_skey[C_ASN1_SKEY_SIZE];
212
0
  struct sc_asn1_entry asn1_supported_algorithms[C_ASN1_SUPPORTED_ALGORITHMS_SIZE];
213
0
  struct sc_asn1_pkcs15_object skey_obj = {
214
0
    (struct sc_pkcs15_object *) obj, asn1_com_key_attr,
215
0
    asn1_com_skey_attr, asn1_generic_skey_attr
216
0
  };
217
218
0
  SC_FUNC_CALLED(ctx, SC_LOG_DEBUG_ASN1);
219
220
0
  sc_copy_asn1_entry(c_asn1_skey, asn1_skey);
221
0
  sc_copy_asn1_entry(c_asn1_skey_choice, asn1_skey_choice);
222
0
  sc_copy_asn1_entry(c_asn1_supported_algorithms, asn1_supported_algorithms);
223
224
0
  sc_copy_asn1_entry(c_asn1_com_key_attr, asn1_com_key_attr);
225
0
  sc_copy_asn1_entry(c_asn1_com_skey_attr, asn1_com_skey_attr);
226
0
  sc_copy_asn1_entry(c_asn1_generic_skey_attr, asn1_generic_skey_attr);
227
0
  sc_copy_asn1_entry(c_asn1_generic_skey_value_attr, asn1_generic_skey_value_attr);
228
229
0
  sc_format_asn1_entry(asn1_skey + 0, asn1_skey_choice, NULL, 1);
230
0
  switch (obj->type) {
231
0
  case SC_PKCS15_TYPE_SKEY_GENERIC:
232
0
    sc_format_asn1_entry(asn1_skey_choice + 0, &skey_obj, NULL, 1);
233
0
    break;
234
0
  case SC_PKCS15_TYPE_SKEY_DES:
235
0
    sc_format_asn1_entry(asn1_skey_choice + 1, &skey_obj, NULL, 1);
236
0
    break;
237
0
  case SC_PKCS15_TYPE_SKEY_2DES:
238
0
    sc_format_asn1_entry(asn1_skey_choice + 2, &skey_obj, NULL, 1);
239
0
    break;
240
0
  case SC_PKCS15_TYPE_SKEY_3DES:
241
0
    sc_format_asn1_entry(asn1_skey_choice + 3, &skey_obj, NULL, 1);
242
0
    break;
243
0
  default:
244
0
    sc_log(ctx, "Invalid secret key type: %X", obj->type);
245
0
    LOG_FUNC_RETURN(ctx, SC_ERROR_INTERNAL);
246
0
    break;
247
0
  }
248
249
0
  sc_format_asn1_entry(asn1_com_key_attr + 0, &skey->id, NULL, 1);
250
0
  sc_format_asn1_entry(asn1_com_key_attr + 1, &skey->usage, &usage_len, 1);
251
0
  if (skey->native == 0)
252
0
    sc_format_asn1_entry(asn1_com_key_attr + 2, &skey->native, NULL, 1);
253
0
  if (skey->access_flags)
254
0
    sc_format_asn1_entry(asn1_com_key_attr + 3, &skey->access_flags, &af_len, 1);
255
0
  if (skey->key_reference >= 0)
256
0
    sc_format_asn1_entry(asn1_com_key_attr + 4, &skey->key_reference, NULL, 1);
257
0
  for (i=0; i<SC_MAX_SUPPORTED_ALGORITHMS && i<C_ASN1_SUPPORTED_ALGORITHMS_SIZE && skey->algo_refs[i]; i++)
258
0
    sc_format_asn1_entry(asn1_supported_algorithms + i, &skey->algo_refs[i], NULL, 1);
259
0
  sc_format_asn1_entry(asn1_com_key_attr + 5, asn1_supported_algorithms, NULL, skey->algo_refs[0] != 0);
260
261
0
  sc_format_asn1_entry(asn1_com_skey_attr + 0, &skey->value_len, NULL, 1);
262
263
0
  sc_format_asn1_entry(asn1_generic_skey_attr + 0, asn1_generic_skey_value_attr, NULL, 1);
264
265
0
  sc_format_asn1_entry(asn1_generic_skey_value_attr + 0, &skey->path, NULL, 1);
266
267
0
  r = sc_asn1_encode(ctx, asn1_skey, buf, buflen);
268
269
0
  sc_log(ctx, "Key path %s", sc_print_path(&skey->path));
270
0
  LOG_FUNC_RETURN(ctx, r);
271
0
}
272
273
void
274
sc_pkcs15_free_skey_info(sc_pkcs15_skey_info_t *info)
275
84
{
276
84
  if (info) {
277
84
    free(info->data.value);
278
84
    free(info);
279
84
  }
280
84
}