• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

canokeys / canokey-core / 6542250495

17 Oct 2023 02:02AM UTC coverage: 78.83%. Remained the same
6542250495

push

github

dangfan
Merge commit 'c2ff833e2' into feature/piv-oath-pgp

67 of 67 new or added lines in 3 files covered. (100.0%)

6129 of 7775 relevant lines covered (78.83%)

566.66 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

84.23
/src/key.c
1
// SPDX-License-Identifier: Apache-2.0
2
#include "ecc.h"
3
#include "memzero.h"
4
#include <common.h>
5
#include <key.h>
6

7
#define KEY_META_ATTR 0xFF
8
#define CEIL_DIV_SQRT2 0xB504F334
9
#define MAX_KEY_TEMPLATE_LENGTH 0x16
10

11
int ck_encode_public_key(const ck_key_t *key, uint8_t *buf, bool include_length) {
12
  int off = 0;
142✔
13

14
  switch (key->meta.type) {
142✔
15
  case SECP256R1:
87✔
16
  case SECP256K1:
17
  case SECP384R1:
18
  case SM2:
19
    if (include_length) {
87✔
20
      buf[off++] = PUBLIC_KEY_LENGTH[key->meta.type] + 3; // tag, length, and 0x04
87✔
21
    }
22
    buf[off++] = 0x86;
87✔
23
    buf[off++] = PUBLIC_KEY_LENGTH[key->meta.type] + 1; // 0x04
87✔
24
    buf[off++] = 0x04;
87✔
25
    memcpy(&buf[off], key->ecc.pub, PUBLIC_KEY_LENGTH[key->meta.type]);
87✔
26
    off += PUBLIC_KEY_LENGTH[key->meta.type];
87✔
27
    break;
87✔
28

29
  case ED25519:
19✔
30
  case X25519:
31
    if (include_length) {
19✔
32
      buf[off++] = PUBLIC_KEY_LENGTH[key->meta.type] + 2; // tag, length
19✔
33
    }
34
    buf[off++] = 0x86;
19✔
35
    buf[off++] = PUBLIC_KEY_LENGTH[key->meta.type];
19✔
36
    memcpy(&buf[off], key->ecc.pub, PUBLIC_KEY_LENGTH[key->meta.type]);
19✔
37
    if (key->meta.type == X25519) {
19✔
38
      swap_big_number_endian(&buf[off]); // Public key of x25519 is encoded in little endian
5✔
39
    }
40
    off += PUBLIC_KEY_LENGTH[key->meta.type];
19✔
41
    break;
19✔
42

43
  case RSA2048:
36✔
44
  case RSA3072:
45
  case RSA4096:
46
    if (include_length) { // 3-byte length
36✔
47
      buf[off++] = 0x82;
36✔
48
      // 6 = modulus: tag (1), length (3); exponent: tag (1), length (1)
49
      buf[off++] = HI(6 + PUBLIC_KEY_LENGTH[key->meta.type] + E_LENGTH);
36✔
50
      buf[off++] = LO(6 + PUBLIC_KEY_LENGTH[key->meta.type] + E_LENGTH);
36✔
51
    }
52
    buf[off++] = 0x81; // modulus
36✔
53
    buf[off++] = 0x82;
36✔
54
    buf[off++] = HI(PUBLIC_KEY_LENGTH[key->meta.type]);
36✔
55
    buf[off++] = LO(PUBLIC_KEY_LENGTH[key->meta.type]);
36✔
56
    rsa_get_public_key(&key->rsa, &buf[off]);
36✔
57
    off += PUBLIC_KEY_LENGTH[key->meta.type];
36✔
58
    buf[off++] = 0x82; // exponent
36✔
59
    buf[off++] = E_LENGTH;
36✔
60
    memcpy(&buf[off], key->rsa.e, E_LENGTH);
36✔
61
    off += E_LENGTH;
36✔
62
    break;
36✔
63

64
  default:
×
65
    return -1;
×
66
  }
67

68
  return off;
142✔
69
}
70

71
int ck_parse_piv_policies(ck_key_t *key, const uint8_t *buf, size_t buf_len) {
72
  const uint8_t *end = buf + buf_len;
75✔
73

74
  while (buf < end) {
153✔
75
    switch (*buf++) {
79✔
76
    case 0xAA:
40✔
77
      DBG_MSG("May have pin policy\n");
40✔
78
      if (buf < end && *buf++ != 0x01) {
40✔
79
        DBG_MSG("Wrong length for pin policy\n");
1✔
80
        return KEY_ERR_LENGTH;
1✔
81
      }
82
      if (buf < end && (*buf > PIN_POLICY_ALWAYS || *buf < PIN_POLICY_NEVER)) {
39✔
83
        DBG_MSG("Wrong data for pin policy\n");
×
84
        return KEY_ERR_DATA;
×
85
      }
86
      key->meta.pin_policy = *buf++;
39✔
87
      break;
39✔
88

89
    case 0xAB:
39✔
90
      DBG_MSG("May have touch policy\n");
39✔
91
      if (buf < end && *buf++ != 0x01) {
39✔
92
        DBG_MSG("Wrong length for touch policy\n");
×
93
        return KEY_ERR_LENGTH;
×
94
      }
95
      if (buf < end && (*buf > TOUCH_POLICY_CACHED || *buf < TOUCH_POLICY_NEVER)) {
39✔
96
        DBG_MSG("Wrong data for touch policy\n");
×
97
        return KEY_ERR_DATA;
×
98
      }
99
      key->meta.touch_policy = *buf++;
39✔
100
      break;
39✔
101
    
102
    default:
×
103
      buf = end;
×
104
      break;
×
105
    }
106
  }
107

108
  return 0;
74✔
109
}
110

111
int ck_parse_piv(ck_key_t *key, const uint8_t *buf, size_t buf_len) {
112
  memzero(key->data, sizeof(rsa_key_t));
20✔
113
  key->meta.origin = KEY_ORIGIN_IMPORTED;
20✔
114

115
  const uint8_t *p = buf;
20✔
116

117
  switch (key->meta.type) {
20✔
118
  case SECP256R1:
11✔
119
  case SECP256K1:
120
  case SECP384R1:
121
  case SM2:
122
  case ED25519:
123
  case X25519: {
124

125
    if (buf_len < PRIVATE_KEY_LENGTH[key->meta.type] + 2) {
11✔
126
      DBG_MSG("too short\n");
×
127
      return KEY_ERR_LENGTH;
×
128
    }
129
    if (*p++ != 0x06) {
11✔
130
      DBG_MSG("invalid tag\n");
×
131
      return KEY_ERR_DATA;
×
132
    }
133
    if (*p++ != PRIVATE_KEY_LENGTH[key->meta.type]) {
11✔
134
      DBG_MSG("invalid private key length\n");
1✔
135
      return KEY_ERR_LENGTH;
1✔
136
    }
137
    memcpy(key->ecc.pri, p, PRIVATE_KEY_LENGTH[key->meta.type]);
10✔
138
    if (!ecc_verify_private_key(key->meta.type, &key->ecc)) {
10✔
139
      memzero(key, sizeof(ck_key_t));
×
140
      return KEY_ERR_DATA;
×
141
    }
142
    if (ecc_complete_key(key->meta.type, &key->ecc) < 0) {
10✔
143
      memzero(key, sizeof(ck_key_t));
×
144
      return KEY_ERR_PROC;
×
145
    }
146
    p += PRIVATE_KEY_LENGTH[key->meta.type];
10✔
147
    break;
10✔
148
  }
149

150
  case RSA2048:
8✔
151
  case RSA3072:
152
  case RSA4096: {
153
    int fail, len;
8✔
154
    size_t length_size;
8✔
155

156
    key->rsa.nbits = PRIVATE_KEY_LENGTH[key->meta.type] * 16;
8✔
157
    *(uint32_t *)key->rsa.e = htobe32(65537);
8✔
158

159
    uint8_t *data_ptr[] = {key->rsa.p, key->rsa.q, key->rsa.dp, key->rsa.dq, key->rsa.qinv};
8✔
160

161
    for (int i = 1; i <= 5; ++i) {
38✔
162
      if ((p - buf) >= buf_len) return KEY_ERR_LENGTH;
32✔
163
      if (*p++ != i) return KEY_ERR_DATA;
32✔
164
      len = tlv_get_length_safe(p, buf_len - (p - buf), &fail, &length_size);
31✔
165
      if (fail) return KEY_ERR_LENGTH;
31✔
166
      if (len > PRIVATE_KEY_LENGTH[key->meta.type]) return KEY_ERR_DATA;
30✔
167
      p += length_size;
30✔
168
      memcpy(data_ptr[i - 1] + (PRIVATE_KEY_LENGTH[key->meta.type] - len), p, len);
30✔
169
      p += len;
30✔
170
    }
171

172
    if (be32toh(*(uint32_t *)key->rsa.p) < CEIL_DIV_SQRT2 || be32toh(*(uint32_t *)key->rsa.q) < CEIL_DIV_SQRT2) {
6✔
173
      memzero(key, sizeof(ck_key_t));
×
174
      return KEY_ERR_DATA;
×
175
    }
176

177
    break;
6✔
178
  }
179

180
  default:
1✔
181
    return -1;
1✔
182
  }
183

184
  return ck_parse_piv_policies(key, p, buf + buf_len - p);
16✔
185
}
186

187
/*
188
 * RSA:
189
 * 7F48 xx Cardholder private key template
190
 *         91 xx e
191
 *         92 xx p
192
 *         93 xx q
193
 *         94 xx qinv
194
 *         95 xx dp
195
 *         96 xx dq
196
 * 5F48 xx Concatenation of key data as defined in DO 7F48
197
 *
198
 * ECC:
199
 * 7F48 xx Cardholder private key template
200
 *         92 xx private key
201
 *         99 xx public key (optional)
202
 * 5F48 xx Concatenation of key data as defined in DO 7F48
203
 */
204
int ck_parse_openpgp(ck_key_t *key, const uint8_t *buf, size_t buf_len) {
205
  memzero(key->data, sizeof(rsa_key_t));
14✔
206
  key->meta.origin = KEY_ORIGIN_IMPORTED;
14✔
207

208
  const uint8_t *p = buf;
14✔
209
  int fail, len;
14✔
210
  size_t length_size;
14✔
211

212
  // Cardholder private key template
213
  if (p + 2 - buf >= buf_len) return KEY_ERR_LENGTH;
14✔
214
  if (*p++ != 0x7F || *p++ != 0x48) return KEY_ERR_DATA;
14✔
215
  len = tlv_get_length_safe(p, buf_len - (p - buf), &fail, &length_size);
14✔
216
  if (fail) return KEY_ERR_LENGTH;
14✔
217
  if (len > MAX_KEY_TEMPLATE_LENGTH) return KEY_ERR_DATA;
14✔
218
  p += length_size;
14✔
219
  const uint8_t *data_tag = p + len; // saved for tag 5F48
14✔
220

221
  switch (key->meta.type) {
14✔
222
  case SECP256R1:
8✔
223
  case SECP256K1:
224
  case SECP384R1:
225
  case SM2:
226
  case ED25519:
227
  case X25519: {
228
    if (p + 1 - buf >= buf_len) return KEY_ERR_LENGTH;
8✔
229
    if (*p++ != 0x92) return KEY_ERR_DATA;
8✔
230
    int data_pri_key_len = tlv_get_length_safe(p, buf_len - (p - buf), &fail, &length_size);
8✔
231
    if (fail) return KEY_ERR_LENGTH;
8✔
232
    if (data_pri_key_len > PRIVATE_KEY_LENGTH[key->meta.type]) return KEY_ERR_DATA;
8✔
233
    p += length_size;
8✔
234

235
    int data_pub_key_len = 0; // this is optional
8✔
236
    if (p < data_tag) {
8✔
237
      if (p + 1 - buf >= buf_len) return KEY_ERR_LENGTH;
1✔
238
      if (*p++ == 0x99) {
1✔
239
        data_pub_key_len = tlv_get_length_safe(p, buf_len - (p - buf), &fail, &length_size);
1✔
240
        if (fail) return KEY_ERR_LENGTH;
1✔
241
        if (data_pub_key_len > PUBLIC_KEY_LENGTH[key->meta.type] + 1) return KEY_ERR_DATA;
1✔
242
      }
243
    }
244

245
    // Concatenation of key data
246
    p = data_tag;
8✔
247
    if (p + 2 - buf >= buf_len) return KEY_ERR_LENGTH;
8✔
248
    if (*p++ != 0x5F || *p++ != 0x48) return KEY_ERR_DATA;
8✔
249
    len = tlv_get_length_safe(p, buf_len - (p - buf), &fail, &length_size);
8✔
250
    if (fail || len != data_pri_key_len + data_pub_key_len) return KEY_ERR_DATA;
8✔
251
    p += length_size;
8✔
252
    int n_leading_zeros = PRIVATE_KEY_LENGTH[key->meta.type] - data_pri_key_len;
8✔
253
    if (p + data_pri_key_len - buf > buf_len) return KEY_ERR_LENGTH;
8✔
254
    memcpy(key->ecc.pri + n_leading_zeros, p, data_pri_key_len);
8✔
255

256
    if (!ecc_verify_private_key(key->meta.type, &key->ecc)) {
8✔
257
      memzero(key, sizeof(ck_key_t));
×
258
      return KEY_ERR_DATA;
×
259
    }
260
    if (ecc_complete_key(key->meta.type, &key->ecc) < 0) {
8✔
261
      memzero(key, sizeof(ck_key_t));
×
262
      return KEY_ERR_PROC;
×
263
    }
264

265
    return 0;
8✔
266
  }
267

268
  case RSA2048:
6✔
269
  case RSA3072:
270
  case RSA4096: {
271
    int qinv_len, dp_len, dq_len;
272

273
    // 0x91: e
274
    if (p + 1 - buf >= buf_len) return KEY_ERR_LENGTH;
6✔
275
    if (*p++ != 0x91) return KEY_ERR_DATA;
6✔
276
    len = tlv_get_length_safe(p, buf_len - (p - buf), &fail, &length_size);
6✔
277
    if (fail) return KEY_ERR_LENGTH;
6✔
278
    if (len != E_LENGTH) return KEY_ERR_DATA;
6✔
279
    p += length_size;
6✔
280

281
    // 0x92: p
282
    if (p + 1 - buf >= buf_len) return KEY_ERR_LENGTH;
6✔
283
    if (*p++ != 0x92) return KEY_ERR_DATA;
6✔
284
    len = tlv_get_length_safe(p, buf_len - (p - buf), &fail, &length_size);
6✔
285
    if (fail) return KEY_ERR_LENGTH;
6✔
286
    if (len != PRIVATE_KEY_LENGTH[key->meta.type]) return KEY_ERR_DATA;
6✔
287
    p += length_size;
6✔
288

289
    // 0x93: q
290
    if (p + 1 - buf >= buf_len) return KEY_ERR_LENGTH;
6✔
291
    if (*p++ != 0x93) return KEY_ERR_DATA;
6✔
292
    len = tlv_get_length_safe(p, buf_len - (p - buf), &fail, &length_size);
6✔
293
    if (fail) return KEY_ERR_LENGTH;
6✔
294
    if (len != PRIVATE_KEY_LENGTH[key->meta.type]) return KEY_ERR_DATA;
6✔
295
    p += length_size;
6✔
296

297
    // 0x94: qinv, may be less than p/q's length
298
    if (p + 1 - buf >= buf_len) return KEY_ERR_LENGTH;
6✔
299
    if (*p++ != 0x94) return KEY_ERR_DATA;
6✔
300
    qinv_len = tlv_get_length_safe(p, buf_len - (p - buf), &fail, &length_size);
6✔
301
    if (fail) return KEY_ERR_LENGTH;
6✔
302
    if (qinv_len > PRIVATE_KEY_LENGTH[key->meta.type]) return KEY_ERR_DATA;
6✔
303
    p += length_size;
6✔
304

305
    // 0x94: dp, may be less than p/q's length
306
    if (p + 1 - buf >= buf_len) return KEY_ERR_LENGTH;
6✔
307
    if (*p++ != 0x95) return KEY_ERR_DATA;
6✔
308
    dp_len = tlv_get_length_safe(p, buf_len - (p - buf), &fail, &length_size);
6✔
309
    if (fail) return KEY_ERR_LENGTH;
6✔
310
    if (dp_len > PRIVATE_KEY_LENGTH[key->meta.type]) return KEY_ERR_DATA;
6✔
311
    p += length_size;
6✔
312

313
    // 0x94: dq, may be less than p/q's length
314
    if (p + 1 - buf >= buf_len) return KEY_ERR_LENGTH;
6✔
315
    if (*p++ != 0x96) return KEY_ERR_DATA;
6✔
316
    dq_len = tlv_get_length_safe(p, buf_len - (p - buf), &fail, &length_size);
6✔
317
    if (fail) return KEY_ERR_LENGTH;
6✔
318
    if (dq_len > PRIVATE_KEY_LENGTH[key->meta.type]) return KEY_ERR_DATA;
6✔
319

320
    // Concatenation of key data
321
    p = data_tag;
6✔
322
    if (p + 2 - buf >= buf_len) return KEY_ERR_LENGTH;
6✔
323
    if (*p++ != 0x5F || *p++ != 0x48) return KEY_ERR_DATA;
6✔
324
    len = tlv_get_length_safe(p, buf_len - (p - buf), &fail, &length_size);
6✔
325
    if (fail) return KEY_ERR_LENGTH;
6✔
326
    if (len != PRIVATE_KEY_LENGTH[key->meta.type] * 2 + qinv_len + dp_len + dq_len + E_LENGTH) return KEY_ERR_DATA;
6✔
327
    p += length_size;
6✔
328

329
    if (p + len - buf > buf_len) return KEY_ERR_LENGTH;
6✔
330
    key->rsa.nbits = PRIVATE_KEY_LENGTH[key->meta.type] * 16;
6✔
331
    memcpy(key->rsa.e, p, E_LENGTH);
6✔
332
    p += E_LENGTH;
6✔
333
    memcpy(key->rsa.p, p, PRIVATE_KEY_LENGTH[key->meta.type]);
6✔
334
    p += PRIVATE_KEY_LENGTH[key->meta.type];
6✔
335
    memcpy(key->rsa.q, p, PRIVATE_KEY_LENGTH[key->meta.type]);
6✔
336
    p += PRIVATE_KEY_LENGTH[key->meta.type];
6✔
337
    memcpy(key->rsa.qinv + PRIVATE_KEY_LENGTH[key->meta.type] - qinv_len, p, qinv_len);
6✔
338
    p += qinv_len;
6✔
339
    memcpy(key->rsa.dp + PRIVATE_KEY_LENGTH[key->meta.type] - dp_len, p, dp_len);
6✔
340
    p += dp_len;
6✔
341
    memcpy(key->rsa.dq + PRIVATE_KEY_LENGTH[key->meta.type] - dq_len, p, dq_len);
6✔
342
    if (be32toh(*(uint32_t *)key->rsa.p) < CEIL_DIV_SQRT2 || be32toh(*(uint32_t *)key->rsa.q) < CEIL_DIV_SQRT2) {
6✔
343
      memzero(key, sizeof(ck_key_t));
×
344
      return KEY_ERR_DATA;
×
345
    }
346

347
    return 0;
6✔
348
  }
349

350
  default:
×
351
    return -1;
×
352
  }
353
}
354

355
int ck_read_key_metadata(const char *path, key_meta_t *meta) {
356
  return read_attr(path, KEY_META_ATTR, meta, sizeof(key_meta_t));
3,918✔
357
}
358

359
int ck_write_key_metadata(const char *path, const key_meta_t *meta) {
360
  return write_attr(path, KEY_META_ATTR, meta, sizeof(key_meta_t));
291✔
361
}
362

363
int ck_read_key(const char *path, ck_key_t *key) {
364
  int err = ck_read_key_metadata(path, &key->meta);
1,623✔
365
  if (err < 0) return err;
1,623✔
366
  return read_file(path, key->data, 0, sizeof(rsa_key_t));
1,623✔
367
}
368

369
int ck_write_key(const char *path, const ck_key_t *key) {
370
  int err = write_file(path, key->data, 0, sizeof(rsa_key_t), 1);
247✔
371
  if (err < 0) return err;
247✔
372
  return ck_write_key_metadata(path, &key->meta);
247✔
373
}
374

375
int ck_generate_key(ck_key_t *key) {
376
  key->meta.origin = KEY_ORIGIN_GENERATED;
83✔
377

378
  if (IS_ECC(key->meta.type)) {
83✔
379
    if (ecc_generate(key->meta.type, &key->ecc) < 0) {
57✔
380
      memzero(key, sizeof(ck_key_t));
×
381
      return -1;
×
382
    }
383
    return 0;
57✔
384
  } else if (IS_RSA(key->meta.type)) {
26✔
385
    if (rsa_generate_key(&key->rsa, PUBLIC_KEY_LENGTH[key->meta.type] * 8) < 0) {
26✔
386
      memzero(key, sizeof(ck_key_t));
×
387
      return -1;
×
388
    }
389
    return 0;
26✔
390
  } else {
391
    return -1;
×
392
  }
393
}
394

395
int ck_sign(const ck_key_t *key, const uint8_t *input, size_t input_len, uint8_t *sig) {
396
  DBG_MSG("Data: ");
76✔
397
  PRINT_HEX(input, input_len);
76✔
398
  if (IS_ECC(key->meta.type)) {
76✔
399
    DBG_MSG("Private Key: ");
67✔
400
    PRINT_HEX(key->ecc.pri, PRIVATE_KEY_LENGTH[key->meta.type]);
67✔
401
    DBG_MSG("Public Key: ");
67✔
402
    PRINT_HEX(key->ecc.pub, PUBLIC_KEY_LENGTH[key->meta.type]);
67✔
403
    if (ecc_sign(key->meta.type, &key->ecc, input, input_len, sig) < 0) {
67✔
404
      ERR_MSG("ECC signing failed\n");
×
405
      DBG_KEY_META(&key->meta);
×
406
      return -1;
×
407
    }
408
  } else if (IS_RSA(key->meta.type)) {
9✔
409
    DBG_MSG("Key: ");
9✔
410
    PRINT_HEX(key->rsa.p, PRIVATE_KEY_LENGTH[key->meta.type]);
9✔
411
    PRINT_HEX(key->rsa.q, PRIVATE_KEY_LENGTH[key->meta.type]);
9✔
412
    if (rsa_sign_pkcs_v15(&key->rsa, input, input_len, sig) < 0) {
9✔
413
      ERR_MSG("RSA signing failed\n");
×
414
      DBG_KEY_META(&key->meta);
×
415
      return -1;
×
416
    }
417
  } else {
418
    return -1;
×
419
  }
420
  DBG_MSG("Sig: ");
76✔
421
  PRINT_HEX(sig, SIGNATURE_LENGTH[key->meta.type]);
76✔
422
  return SIGNATURE_LENGTH[key->meta.type];
76✔
423
}
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2026 Coveralls, Inc