/src/opensc/src/libopensc/pkcs15-sc-hsm.c
Line | Count | Source |
1 | | /* |
2 | | * pkcs15-sc-hsm.c : Initialize PKCS#15 emulation |
3 | | * |
4 | | * Copyright (C) 2012 Andreas Schwier, CardContact, Minden, Germany |
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 | | |
29 | | #include "internal.h" |
30 | | #include "pkcs15.h" |
31 | | #include "asn1.h" |
32 | | #include "common/compat_strlcpy.h" |
33 | | #include "common/compat_strnlen.h" |
34 | | |
35 | | #include "card-sc-hsm.h" |
36 | | |
37 | | |
38 | | extern struct sc_aid sc_hsm_aid; |
39 | | |
40 | | |
41 | | void sc_hsm_set_serialnr(sc_card_t *card, char *serial); |
42 | | |
43 | | // clang-format off |
44 | | static struct ec_curve curves[] = { |
45 | | { |
46 | | { (unsigned char *) "\x2A\x86\x48\xCE\x3D\x03\x01\x01", 8}, // secp192r1 aka prime192r1 |
47 | | { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 24}, |
48 | | { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFC", 24}, |
49 | | { (unsigned char *) "\x64\x21\x05\x19\xE5\x9C\x80\xE7\x0F\xA7\xE9\xAB\x72\x24\x30\x49\xFE\xB8\xDE\xEC\xC1\x46\xB9\xB1", 24}, |
50 | | { (unsigned char *) "\x04\x18\x8D\xA8\x0E\xB0\x30\x90\xF6\x7C\xBF\x20\xEB\x43\xA1\x88\x00\xF4\xFF\x0A\xFD\x82\xFF\x10\x12\x07\x19\x2B\x95\xFF\xC8\xDA\x78\x63\x10\x11\xED\x6B\x24\xCD\xD5\x73\xF9\x77\xA1\x1E\x79\x48\x11", 49}, |
51 | | { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\x99\xDE\xF8\x36\x14\x6B\xC9\xB1\xB4\xD2\x28\x31", 24}, |
52 | | { (unsigned char *) "\x01", 1} |
53 | | }, |
54 | | { |
55 | | { (unsigned char *) "\x2A\x86\x48\xCE\x3D\x03\x01\x07", 8}, // secp256r1 aka prime256r1 |
56 | | { (unsigned char *) "\xFF\xFF\xFF\xFF\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 32}, |
57 | | { (unsigned char *) "\xFF\xFF\xFF\xFF\x00\x00\x00\x01\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFC", 32}, |
58 | | { (unsigned char *) "\x5A\xC6\x35\xD8\xAA\x3A\x93\xE7\xB3\xEB\xBD\x55\x76\x98\x86\xBC\x65\x1D\x06\xB0\xCC\x53\xB0\xF6\x3B\xCE\x3C\x3E\x27\xD2\x60\x4B", 32}, |
59 | | { (unsigned char *) "\x04\x6B\x17\xD1\xF2\xE1\x2C\x42\x47\xF8\xBC\xE6\xE5\x63\xA4\x40\xF2\x77\x03\x7D\x81\x2D\xEB\x33\xA0\xF4\xA1\x39\x45\xD8\x98\xC2\x96\x4F\xE3\x42\xE2\xFE\x1A\x7F\x9B\x8E\xE7\xEB\x4A\x7C\x0F\x9E\x16\x2B\xCE\x33\x57\x6B\x31\x5E\xCE\xCB\xB6\x40\x68\x37\xBF\x51\xF5", 65}, |
60 | | { (unsigned char *) "\xFF\xFF\xFF\xFF\x00\x00\x00\x00\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xBC\xE6\xFA\xAD\xA7\x17\x9E\x84\xF3\xB9\xCA\xC2\xFC\x63\x25\x51", 32}, |
61 | | { (unsigned char *) "\x01", 1} |
62 | | }, |
63 | | { |
64 | | { (unsigned char *) "\x2B\x81\x04\x00\x22", 5}, // secp384r1 |
65 | | { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFF", 48}, |
66 | | { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xFF\xFF\x00\x00\x00\x00\x00\x00\x00\x00\xFF\xFF\xFF\xFC", 48}, |
67 | | { (unsigned char *) "\xB3\x31\x2F\xA7\xE2\x3E\xE7\xE4\x98\x8E\x05\x6B\xE3\xF8\x2D\x19\x18\x1D\x9C\x6E\xFE\x81\x41\x12\x03\x14\x08\x8F\x50\x13\x87\x5A\xC6\x56\x39\x8D\x8A\x2E\xD1\x9D\x2A\x85\xC8\xED\xD3\xEC\x2A\xEF", 48}, |
68 | | { (unsigned char *) "\x04\xAA\x87\xCA\x22\xBE\x8B\x05\x37\x8E\xB1\xC7\x1E\xF3\x20\xAD\x74\x6E\x1D\x3B\x62\x8B\xA7\x9B\x98\x59\xF7\x41\xE0\x82\x54\x2A\x38\x55\x02\xF2\x5D\xBF\x55\x29\x6C\x3A\x54\x5E\x38\x72\x76\x0A\xB7\x36\x17\xDE\x4A\x96\x26\x2C\x6F\x5D\x9E\x98\xBF\x92\x92\xDC\x29\xF8\xF4\x1D\xBD\x28\x9A\x14\x7C\xE9\xDA\x31\x13\xB5\xF0\xB8\xC0\x0A\x60\xB1\xCE\x1D\x7E\x81\x9D\x7A\x43\x1D\x7C\x90\xEA\x0E\x5F", 97}, |
69 | | { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xC7\x63\x4D\x81\xF4\x37\x2D\xDF\x58\x1A\x0D\xB2\x48\xB0\xA7\x7A\xEC\xEC\x19\x6A\xCC\xC5\x29\x73", 48}, |
70 | | { (unsigned char *) "\x01", 1} |
71 | | }, |
72 | | { |
73 | | { (unsigned char *) "\x2B\x81\x04\x00\x23", 5}, // secp521r1 |
74 | | { (unsigned char *) "\x01\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 66}, |
75 | | { (unsigned char *) "\x01\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFC", 66}, |
76 | | { (unsigned char *) "\x00\x51\x95\x3E\xB9\x61\x8E\x1C\x9A\x1F\x92\x9A\x21\xA0\xB6\x85\x40\xEE\xA2\xDA\x72\x5B\x99\xB3\x15\xF3\xB8\xB4\x89\x91\x8E\xF1\x09\xE1\x56\x19\x39\x51\xEC\x7E\x93\x7B\x16\x52\xC0\xBD\x3B\xB1\xBF\x07\x35\x73\xDF\x88\x3D\x2C\x34\xF1\xEF\x45\x1F\xD4\x6B\x50\x3F\x00", 66}, |
77 | | { (unsigned char *) "\x04\x00\xC6\x85\x8E\x06\xB7\x04\x04\xE9\xCD\x9E\x3E\xCB\x66\x23\x95\xB4\x42\x9C\x64\x81\x39\x05\x3F\xB5\x21\xF8\x28\xAF\x60\x6B\x4D\x3D\xBA\xA1\x4B\x5E\x77\xEF\xE7\x59\x28\xFE\x1D\xC1\x27\xA2\xFF\xA8\xDE\x33\x48\xB3\xC1\x85\x6A\x42\x9B\xF9\x7E\x7E\x31\xC2\xE5\xBD\x66\x01\x18\x39\x29\x6A\x78\x9A\x3B\xC0\x04\x5C\x8A\x5F\xB4\x2C\x7D\x1B\xD9\x98\xF5\x44\x49\x57\x9B\x44\x68\x17\xAF\xBD\x17\x27\x3E\x66\x2C\x97\xEE\x72\x99\x5E\xF4\x26\x40\xC5\x50\xB9\x01\x3F\xAD\x07\x61\x35\x3C\x70\x86\xA2\x72\xC2\x40\x88\xBE\x94\x76\x9F\xD1\x66\x50", 133}, |
78 | | { (unsigned char *) "\x01\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFA\x51\x86\x87\x83\xBF\x2F\x96\x6B\x7F\xCC\x01\x48\xF7\x09\xA5\xD0\x3B\xB5\xC9\xB8\x89\x9C\x47\xAE\xBB\x6F\xB7\x1E\x91\x38\x64\x09", 66}, |
79 | | { (unsigned char *) "\x01", 1} |
80 | | }, |
81 | | { |
82 | | { (unsigned char *) "\x2B\x24\x03\x03\x02\x08\x01\x01\x03", 9}, // brainpoolP192r1 |
83 | | { (unsigned char *) "\xC3\x02\xF4\x1D\x93\x2A\x36\xCD\xA7\xA3\x46\x30\x93\xD1\x8D\xB7\x8F\xCE\x47\x6D\xE1\xA8\x62\x97", 24}, |
84 | | { (unsigned char *) "\x6A\x91\x17\x40\x76\xB1\xE0\xE1\x9C\x39\xC0\x31\xFE\x86\x85\xC1\xCA\xE0\x40\xE5\xC6\x9A\x28\xEF", 24}, |
85 | | { (unsigned char *) "\x46\x9A\x28\xEF\x7C\x28\xCC\xA3\xDC\x72\x1D\x04\x4F\x44\x96\xBC\xCA\x7E\xF4\x14\x6F\xBF\x25\xC9", 24}, |
86 | | { (unsigned char *) "\x04\xC0\xA0\x64\x7E\xAA\xB6\xA4\x87\x53\xB0\x33\xC5\x6C\xB0\xF0\x90\x0A\x2F\x5C\x48\x53\x37\x5F\xD6\x14\xB6\x90\x86\x6A\xBD\x5B\xB8\x8B\x5F\x48\x28\xC1\x49\x00\x02\xE6\x77\x3F\xA2\xFA\x29\x9B\x8F", 49}, |
87 | | { (unsigned char *) "\xC3\x02\xF4\x1D\x93\x2A\x36\xCD\xA7\xA3\x46\x2F\x9E\x9E\x91\x6B\x5B\xE8\xF1\x02\x9A\xC4\xAC\xC1", 24}, |
88 | | { (unsigned char *) "\x01", 1} |
89 | | }, |
90 | | { |
91 | | { (unsigned char *) "\x2B\x24\x03\x03\x02\x08\x01\x01\x05", 9}, // brainpoolP224r1 |
92 | | { (unsigned char *) "\xD7\xC1\x34\xAA\x26\x43\x66\x86\x2A\x18\x30\x25\x75\xD1\xD7\x87\xB0\x9F\x07\x57\x97\xDA\x89\xF5\x7E\xC8\xC0\xFF", 28}, |
93 | | { (unsigned char *) "\x68\xA5\xE6\x2C\xA9\xCE\x6C\x1C\x29\x98\x03\xA6\xC1\x53\x0B\x51\x4E\x18\x2A\xD8\xB0\x04\x2A\x59\xCA\xD2\x9F\x43", 28}, |
94 | | { (unsigned char *) "\x25\x80\xF6\x3C\xCF\xE4\x41\x38\x87\x07\x13\xB1\xA9\x23\x69\xE3\x3E\x21\x35\xD2\x66\xDB\xB3\x72\x38\x6C\x40\x0B", 28}, |
95 | | { (unsigned char *) "\x04\x0D\x90\x29\xAD\x2C\x7E\x5C\xF4\x34\x08\x23\xB2\xA8\x7D\xC6\x8C\x9E\x4C\xE3\x17\x4C\x1E\x6E\xFD\xEE\x12\xC0\x7D\x58\xAA\x56\xF7\x72\xC0\x72\x6F\x24\xC6\xB8\x9E\x4E\xCD\xAC\x24\x35\x4B\x9E\x99\xCA\xA3\xF6\xD3\x76\x14\x02\xCD", 57}, |
96 | | { (unsigned char *) "\xD7\xC1\x34\xAA\x26\x43\x66\x86\x2A\x18\x30\x25\x75\xD0\xFB\x98\xD1\x16\xBC\x4B\x6D\xDE\xBC\xA3\xA5\xA7\x93\x9F", 28}, |
97 | | { (unsigned char *) "\x01", 1} |
98 | | }, |
99 | | { |
100 | | { (unsigned char *) "\x2B\x24\x03\x03\x02\x08\x01\x01\x07", 9}, // brainpoolP256r1 |
101 | | { (unsigned char *) "\xA9\xFB\x57\xDB\xA1\xEE\xA9\xBC\x3E\x66\x0A\x90\x9D\x83\x8D\x72\x6E\x3B\xF6\x23\xD5\x26\x20\x28\x20\x13\x48\x1D\x1F\x6E\x53\x77", 32}, |
102 | | { (unsigned char *) "\x7D\x5A\x09\x75\xFC\x2C\x30\x57\xEE\xF6\x75\x30\x41\x7A\xFF\xE7\xFB\x80\x55\xC1\x26\xDC\x5C\x6C\xE9\x4A\x4B\x44\xF3\x30\xB5\xD9", 32}, |
103 | | { (unsigned char *) "\x26\xDC\x5C\x6C\xE9\x4A\x4B\x44\xF3\x30\xB5\xD9\xBB\xD7\x7C\xBF\x95\x84\x16\x29\x5C\xF7\xE1\xCE\x6B\xCC\xDC\x18\xFF\x8C\x07\xB6", 32}, |
104 | | { (unsigned char *) "\x04\x8B\xD2\xAE\xB9\xCB\x7E\x57\xCB\x2C\x4B\x48\x2F\xFC\x81\xB7\xAF\xB9\xDE\x27\xE1\xE3\xBD\x23\xC2\x3A\x44\x53\xBD\x9A\xCE\x32\x62\x54\x7E\xF8\x35\xC3\xDA\xC4\xFD\x97\xF8\x46\x1A\x14\x61\x1D\xC9\xC2\x77\x45\x13\x2D\xED\x8E\x54\x5C\x1D\x54\xC7\x2F\x04\x69\x97", 65}, |
105 | | { (unsigned char *) "\xA9\xFB\x57\xDB\xA1\xEE\xA9\xBC\x3E\x66\x0A\x90\x9D\x83\x8D\x71\x8C\x39\x7A\xA3\xB5\x61\xA6\xF7\x90\x1E\x0E\x82\x97\x48\x56\xA7", 32}, |
106 | | { (unsigned char *) "\x01", 1} |
107 | | }, |
108 | | { |
109 | | { (unsigned char *) "\x2B\x24\x03\x03\x02\x08\x01\x01\x09", 9}, // brainpoolP320r1 |
110 | | { (unsigned char *) "\xD3\x5E\x47\x20\x36\xBC\x4F\xB7\xE1\x3C\x78\x5E\xD2\x01\xE0\x65\xF9\x8F\xCF\xA6\xF6\xF4\x0D\xEF\x4F\x92\xB9\xEC\x78\x93\xEC\x28\xFC\xD4\x12\xB1\xF1\xB3\x2E\x27", 40}, |
111 | | { (unsigned char *) "\x3E\xE3\x0B\x56\x8F\xBA\xB0\xF8\x83\xCC\xEB\xD4\x6D\x3F\x3B\xB8\xA2\xA7\x35\x13\xF5\xEB\x79\xDA\x66\x19\x0E\xB0\x85\xFF\xA9\xF4\x92\xF3\x75\xA9\x7D\x86\x0E\xB4", 40}, |
112 | | { (unsigned char *) "\x52\x08\x83\x94\x9D\xFD\xBC\x42\xD3\xAD\x19\x86\x40\x68\x8A\x6F\xE1\x3F\x41\x34\x95\x54\xB4\x9A\xCC\x31\xDC\xCD\x88\x45\x39\x81\x6F\x5E\xB4\xAC\x8F\xB1\xF1\xA6", 40}, |
113 | | { (unsigned char *) "\x04\x43\xBD\x7E\x9A\xFB\x53\xD8\xB8\x52\x89\xBC\xC4\x8E\xE5\xBF\xE6\xF2\x01\x37\xD1\x0A\x08\x7E\xB6\xE7\x87\x1E\x2A\x10\xA5\x99\xC7\x10\xAF\x8D\x0D\x39\xE2\x06\x11\x14\xFD\xD0\x55\x45\xEC\x1C\xC8\xAB\x40\x93\x24\x7F\x77\x27\x5E\x07\x43\xFF\xED\x11\x71\x82\xEA\xA9\xC7\x78\x77\xAA\xAC\x6A\xC7\xD3\x52\x45\xD1\x69\x2E\x8E\xE1", 81}, |
114 | | { (unsigned char *) "\xD3\x5E\x47\x20\x36\xBC\x4F\xB7\xE1\x3C\x78\x5E\xD2\x01\xE0\x65\xF9\x8F\xCF\xA5\xB6\x8F\x12\xA3\x2D\x48\x2E\xC7\xEE\x86\x58\xE9\x86\x91\x55\x5B\x44\xC5\x93\x11", 40}, |
115 | | { (unsigned char *) "\x01", 1} |
116 | | }, |
117 | | { |
118 | | { (unsigned char *) "\x2B\x24\x03\x03\x02\x08\x01\x01\x0B", 9}, // brainpoolP384r1 |
119 | | { (unsigned char *) "\x8C\xB9\x1E\x82\xA3\x38\x6D\x28\x0F\x5D\x6F\x7E\x50\xE6\x41\xDF\x15\x2F\x71\x09\xED\x54\x56\xB4\x12\xB1\xDA\x19\x7F\xB7\x11\x23\xAC\xD3\xA7\x29\x90\x1D\x1A\x71\x87\x47\x00\x13\x31\x07\xEC\x53", 48}, |
120 | | { (unsigned char *) "\x7B\xC3\x82\xC6\x3D\x8C\x15\x0C\x3C\x72\x08\x0A\xCE\x05\xAF\xA0\xC2\xBE\xA2\x8E\x4F\xB2\x27\x87\x13\x91\x65\xEF\xBA\x91\xF9\x0F\x8A\xA5\x81\x4A\x50\x3A\xD4\xEB\x04\xA8\xC7\xDD\x22\xCE\x28\x26", 48}, |
121 | | { (unsigned char *) "\x04\xA8\xC7\xDD\x22\xCE\x28\x26\x8B\x39\xB5\x54\x16\xF0\x44\x7C\x2F\xB7\x7D\xE1\x07\xDC\xD2\xA6\x2E\x88\x0E\xA5\x3E\xEB\x62\xD5\x7C\xB4\x39\x02\x95\xDB\xC9\x94\x3A\xB7\x86\x96\xFA\x50\x4C\x11", 48}, |
122 | | { (unsigned char *) "\x04\x1D\x1C\x64\xF0\x68\xCF\x45\xFF\xA2\xA6\x3A\x81\xB7\xC1\x3F\x6B\x88\x47\xA3\xE7\x7E\xF1\x4F\xE3\xDB\x7F\xCA\xFE\x0C\xBD\x10\xE8\xE8\x26\xE0\x34\x36\xD6\x46\xAA\xEF\x87\xB2\xE2\x47\xD4\xAF\x1E\x8A\xBE\x1D\x75\x20\xF9\xC2\xA4\x5C\xB1\xEB\x8E\x95\xCF\xD5\x52\x62\xB7\x0B\x29\xFE\xEC\x58\x64\xE1\x9C\x05\x4F\xF9\x91\x29\x28\x0E\x46\x46\x21\x77\x91\x81\x11\x42\x82\x03\x41\x26\x3C\x53\x15", 97}, |
123 | | { (unsigned char *) "\x8C\xB9\x1E\x82\xA3\x38\x6D\x28\x0F\x5D\x6F\x7E\x50\xE6\x41\xDF\x15\x2F\x71\x09\xED\x54\x56\xB3\x1F\x16\x6E\x6C\xAC\x04\x25\xA7\xCF\x3A\xB6\xAF\x6B\x7F\xC3\x10\x3B\x88\x32\x02\xE9\x04\x65\x65", 48}, |
124 | | { (unsigned char *) "\x01", 1} |
125 | | }, |
126 | | { |
127 | | { (unsigned char *) "\x2B\x24\x03\x03\x02\x08\x01\x01\x0D", 9}, // brainpoolP512r1 |
128 | | { (unsigned char *) "\xAA\xDD\x9D\xB8\xDB\xE9\xC4\x8B\x3F\xD4\xE6\xAE\x33\xC9\xFC\x07\xCB\x30\x8D\xB3\xB3\xC9\xD2\x0E\xD6\x63\x9C\xCA\x70\x33\x08\x71\x7D\x4D\x9B\x00\x9B\xC6\x68\x42\xAE\xCD\xA1\x2A\xE6\xA3\x80\xE6\x28\x81\xFF\x2F\x2D\x82\xC6\x85\x28\xAA\x60\x56\x58\x3A\x48\xF3", 64}, |
129 | | { (unsigned char *) "\x78\x30\xA3\x31\x8B\x60\x3B\x89\xE2\x32\x71\x45\xAC\x23\x4C\xC5\x94\xCB\xDD\x8D\x3D\xF9\x16\x10\xA8\x34\x41\xCA\xEA\x98\x63\xBC\x2D\xED\x5D\x5A\xA8\x25\x3A\xA1\x0A\x2E\xF1\xC9\x8B\x9A\xC8\xB5\x7F\x11\x17\xA7\x2B\xF2\xC7\xB9\xE7\xC1\xAC\x4D\x77\xFC\x94\xCA", 64}, |
130 | | { (unsigned char *) "\x3D\xF9\x16\x10\xA8\x34\x41\xCA\xEA\x98\x63\xBC\x2D\xED\x5D\x5A\xA8\x25\x3A\xA1\x0A\x2E\xF1\xC9\x8B\x9A\xC8\xB5\x7F\x11\x17\xA7\x2B\xF2\xC7\xB9\xE7\xC1\xAC\x4D\x77\xFC\x94\xCA\xDC\x08\x3E\x67\x98\x40\x50\xB7\x5E\xBA\xE5\xDD\x28\x09\xBD\x63\x80\x16\xF7\x23", 64}, |
131 | | { (unsigned char *) "\x04\x81\xAE\xE4\xBD\xD8\x2E\xD9\x64\x5A\x21\x32\x2E\x9C\x4C\x6A\x93\x85\xED\x9F\x70\xB5\xD9\x16\xC1\xB4\x3B\x62\xEE\xF4\xD0\x09\x8E\xFF\x3B\x1F\x78\xE2\xD0\xD4\x8D\x50\xD1\x68\x7B\x93\xB9\x7D\x5F\x7C\x6D\x50\x47\x40\x6A\x5E\x68\x8B\x35\x22\x09\xBC\xB9\xF8\x22\x7D\xDE\x38\x5D\x56\x63\x32\xEC\xC0\xEA\xBF\xA9\xCF\x78\x22\xFD\xF2\x09\xF7\x00\x24\xA5\x7B\x1A\xA0\x00\xC5\x5B\x88\x1F\x81\x11\xB2\xDC\xDE\x49\x4A\x5F\x48\x5E\x5B\xCA\x4B\xD8\x8A\x27\x63\xAE\xD1\xCA\x2B\x2F\xA8\xF0\x54\x06\x78\xCD\x1E\x0F\x3A\xD8\x08\x92", 129}, |
132 | | { (unsigned char *) "\xAA\xDD\x9D\xB8\xDB\xE9\xC4\x8B\x3F\xD4\xE6\xAE\x33\xC9\xFC\x07\xCB\x30\x8D\xB3\xB3\xC9\xD2\x0E\xD6\x63\x9C\xCA\x70\x33\x08\x70\x55\x3E\x5C\x41\x4C\xA9\x26\x19\x41\x86\x61\x19\x7F\xAC\x10\x47\x1D\xB1\xD3\x81\x08\x5D\xDA\xDD\xB5\x87\x96\x82\x9C\xA9\x00\x69", 64}, |
133 | | { (unsigned char *) "\x01", 1} |
134 | | }, |
135 | | { |
136 | | { (unsigned char *) "\x2B\x24\x03\x03\x02\x08\x01\x01\x04", 9}, // brainpoolP192t1 |
137 | | { (unsigned char *) "\xC3\x02\xF4\x1D\x93\x2A\x36\xCD\xA7\xA3\x46\x30\x93\xD1\x8D\xB7\x8F\xCE\x47\x6D\xE1\xA8\x62\x97", 24}, |
138 | | { (unsigned char *) "\xC3\x02\xF4\x1D\x93\x2A\x36\xCD\xA7\xA3\x46\x30\x93\xD1\x8D\xB7\x8F\xCE\x47\x6D\xE1\xA8\x62\x94", 24}, |
139 | | { (unsigned char *) "\x13\xD5\x6F\xFA\xEC\x78\x68\x1E\x68\xF9\xDE\xB4\x3B\x35\xBE\xC2\xFB\x68\x54\x2E\x27\x89\x7B\x79", 24}, |
140 | | { (unsigned char *) "\x04\x3A\xE9\xE5\x8C\x82\xF6\x3C\x30\x28\x2E\x1F\xE7\xBB\xF4\x3F\xA7\x2C\x44\x6A\xF6\xF4\x61\x81\x29\x09\x7E\x2C\x56\x67\xC2\x22\x3A\x90\x2A\xB5\xCA\x44\x9D\x00\x84\xB7\xE5\xB3\xDE\x7C\xCC\x01\xC9", 49}, |
141 | | { (unsigned char *) "\xC3\x02\xF4\x1D\x93\x2A\x36\xCD\xA7\xA3\x46\x2F\x9E\x9E\x91\x6B\x5B\xE8\xF1\x02\x9A\xC4\xAC\xC1", 24}, |
142 | | { (unsigned char *) "\x01", 1} |
143 | | }, |
144 | | { |
145 | | { (unsigned char *) "\x2B\x24\x03\x03\x02\x08\x01\x01\x06", 9}, // brainpoolP224t1 |
146 | | { (unsigned char *) "\xD7\xC1\x34\xAA\x26\x43\x66\x86\x2A\x18\x30\x25\x75\xD1\xD7\x87\xB0\x9F\x07\x57\x97\xDA\x89\xF5\x7E\xC8\xC0\xFF", 28}, |
147 | | { (unsigned char *) "\xD7\xC1\x34\xAA\x26\x43\x66\x86\x2A\x18\x30\x25\x75\xD1\xD7\x87\xB0\x9F\x07\x57\x97\xDA\x89\xF5\x7E\xC8\xC0\xFC", 28}, |
148 | | { (unsigned char *) "\x4B\x33\x7D\x93\x41\x04\xCD\x7B\xEF\x27\x1B\xF6\x0C\xED\x1E\xD2\x0D\xA1\x4C\x08\xB3\xBB\x64\xF1\x8A\x60\x88\x8D", 28}, |
149 | | { (unsigned char *) "\x04\x6A\xB1\xE3\x44\xCE\x25\xFF\x38\x96\x42\x4E\x7F\xFE\x14\x76\x2E\xCB\x49\xF8\x92\x8A\xC0\xC7\x60\x29\xB4\xD5\x80\x03\x74\xE9\xF5\x14\x3E\x56\x8C\xD2\x3F\x3F\x4D\x7C\x0D\x4B\x1E\x41\xC8\xCC\x0D\x1C\x6A\xBD\x5F\x1A\x46\xDB\x4C", 57}, |
150 | | { (unsigned char *) "\xD7\xC1\x34\xAA\x26\x43\x66\x86\x2A\x18\x30\x25\x75\xD0\xFB\x98\xD1\x16\xBC\x4B\x6D\xDE\xBC\xA3\xA5\xA7\x93\x9F", 28}, |
151 | | { (unsigned char *) "\x01", 1} |
152 | | }, |
153 | | { |
154 | | { (unsigned char *) "\x2B\x24\x03\x03\x02\x08\x01\x01\x08", 9}, // brainpoolP256t1 |
155 | | { (unsigned char *) "\xA9\xFB\x57\xDB\xA1\xEE\xA9\xBC\x3E\x66\x0A\x90\x9D\x83\x8D\x72\x6E\x3B\xF6\x23\xD5\x26\x20\x28\x20\x13\x48\x1D\x1F\x6E\x53\x77", 32}, |
156 | | { (unsigned char *) "\xA9\xFB\x57\xDB\xA1\xEE\xA9\xBC\x3E\x66\x0A\x90\x9D\x83\x8D\x72\x6E\x3B\xF6\x23\xD5\x26\x20\x28\x20\x13\x48\x1D\x1F\x6E\x53\x74", 32}, |
157 | | { (unsigned char *) "\x66\x2C\x61\xC4\x30\xD8\x4E\xA4\xFE\x66\xA7\x73\x3D\x0B\x76\xB7\xBF\x93\xEB\xC4\xAF\x2F\x49\x25\x6A\xE5\x81\x01\xFE\xE9\x2B\x04", 32}, |
158 | | { (unsigned char *) "\x04\xA3\xE8\xEB\x3C\xC1\xCF\xE7\xB7\x73\x22\x13\xB2\x3A\x65\x61\x49\xAF\xA1\x42\xC4\x7A\xAF\xBC\x2B\x79\xA1\x91\x56\x2E\x13\x05\xF4\x2D\x99\x6C\x82\x34\x39\xC5\x6D\x7F\x7B\x22\xE1\x46\x44\x41\x7E\x69\xBC\xB6\xDE\x39\xD0\x27\x00\x1D\xAB\xE8\xF3\x5B\x25\xC9\xBE", 65}, |
159 | | { (unsigned char *) "\xA9\xFB\x57\xDB\xA1\xEE\xA9\xBC\x3E\x66\x0A\x90\x9D\x83\x8D\x71\x8C\x39\x7A\xA3\xB5\x61\xA6\xF7\x90\x1E\x0E\x82\x97\x48\x56\xA7", 32}, |
160 | | { (unsigned char *) "\x01", 1} |
161 | | }, |
162 | | { |
163 | | { (unsigned char *) "\x2B\x24\x03\x03\x02\x08\x01\x01\x0A", 9}, // brainpoolP320t1 |
164 | | { (unsigned char *) "\xD3\x5E\x47\x20\x36\xBC\x4F\xB7\xE1\x3C\x78\x5E\xD2\x01\xE0\x65\xF9\x8F\xCF\xA6\xF6\xF4\x0D\xEF\x4F\x92\xB9\xEC\x78\x93\xEC\x28\xFC\xD4\x12\xB1\xF1\xB3\x2E\x27", 40}, |
165 | | { (unsigned char *) "\xD3\x5E\x47\x20\x36\xBC\x4F\xB7\xE1\x3C\x78\x5E\xD2\x01\xE0\x65\xF9\x8F\xCF\xA6\xF6\xF4\x0D\xEF\x4F\x92\xB9\xEC\x78\x93\xEC\x28\xFC\xD4\x12\xB1\xF1\xB3\x2E\x24", 40}, |
166 | | { (unsigned char *) "\xA7\xF5\x61\xE0\x38\xEB\x1E\xD5\x60\xB3\xD1\x47\xDB\x78\x20\x13\x06\x4C\x19\xF2\x7E\xD2\x7C\x67\x80\xAA\xF7\x7F\xB8\xA5\x47\xCE\xB5\xB4\xFE\xF4\x22\x34\x03\x53", 40}, |
167 | | { (unsigned char *) "\x04\x92\x5B\xE9\xFB\x01\xAF\xC6\xFB\x4D\x3E\x7D\x49\x90\x01\x0F\x81\x34\x08\xAB\x10\x6C\x4F\x09\xCB\x7E\xE0\x78\x68\xCC\x13\x6F\xFF\x33\x57\xF6\x24\xA2\x1B\xED\x52\x63\xBA\x3A\x7A\x27\x48\x3E\xBF\x66\x71\xDB\xEF\x7A\xBB\x30\xEB\xEE\x08\x4E\x58\xA0\xB0\x77\xAD\x42\xA5\xA0\x98\x9D\x1E\xE7\x1B\x1B\x9B\xC0\x45\x5F\xB0\xD2\xC3", 81}, |
168 | | { (unsigned char *) "\xD3\x5E\x47\x20\x36\xBC\x4F\xB7\xE1\x3C\x78\x5E\xD2\x01\xE0\x65\xF9\x8F\xCF\xA5\xB6\x8F\x12\xA3\x2D\x48\x2E\xC7\xEE\x86\x58\xE9\x86\x91\x55\x5B\x44\xC5\x93\x11", 40}, |
169 | | { (unsigned char *) "\x01", 1} |
170 | | }, |
171 | | { |
172 | | { (unsigned char *) "\x2B\x24\x03\x03\x02\x08\x01\x01\x0C", 9}, // brainpoolP384t1 |
173 | | { (unsigned char *) "\x8C\xB9\x1E\x82\xA3\x38\x6D\x28\x0F\x5D\x6F\x7E\x50\xE6\x41\xDF\x15\x2F\x71\x09\xED\x54\x56\xB4\x12\xB1\xDA\x19\x7F\xB7\x11\x23\xAC\xD3\xA7\x29\x90\x1D\x1A\x71\x87\x47\x00\x13\x31\x07\xEC\x53", 48}, |
174 | | { (unsigned char *) "\x8C\xB9\x1E\x82\xA3\x38\x6D\x28\x0F\x5D\x6F\x7E\x50\xE6\x41\xDF\x15\x2F\x71\x09\xED\x54\x56\xB4\x12\xB1\xDA\x19\x7F\xB7\x11\x23\xAC\xD3\xA7\x29\x90\x1D\x1A\x71\x87\x47\x00\x13\x31\x07\xEC\x50", 48}, |
175 | | { (unsigned char *) "\x7F\x51\x9E\xAD\xA7\xBD\xA8\x1B\xD8\x26\xDB\xA6\x47\x91\x0F\x8C\x4B\x93\x46\xED\x8C\xCD\xC6\x4E\x4B\x1A\xBD\x11\x75\x6D\xCE\x1D\x20\x74\xAA\x26\x3B\x88\x80\x5C\xED\x70\x35\x5A\x33\xB4\x71\xEE", 48}, |
176 | | { (unsigned char *) "\x04\x18\xDE\x98\xB0\x2D\xB9\xA3\x06\xF2\xAF\xCD\x72\x35\xF7\x2A\x81\x9B\x80\xAB\x12\xEB\xD6\x53\x17\x24\x76\xFE\xCD\x46\x2A\xAB\xFF\xC4\xFF\x19\x1B\x94\x6A\x5F\x54\xD8\xD0\xAA\x2F\x41\x88\x08\xCC\x25\xAB\x05\x69\x62\xD3\x06\x51\xA1\x14\xAF\xD2\x75\x5A\xD3\x36\x74\x7F\x93\x47\x5B\x7A\x1F\xCA\x3B\x88\xF2\xB6\xA2\x08\xCC\xFE\x46\x94\x08\x58\x4D\xC2\xB2\x91\x26\x75\xBF\x5B\x9E\x58\x29\x28", 97}, |
177 | | { (unsigned char *) "\x8C\xB9\x1E\x82\xA3\x38\x6D\x28\x0F\x5D\x6F\x7E\x50\xE6\x41\xDF\x15\x2F\x71\x09\xED\x54\x56\xB3\x1F\x16\x6E\x6C\xAC\x04\x25\xA7\xCF\x3A\xB6\xAF\x6B\x7F\xC3\x10\x3B\x88\x32\x02\xE9\x04\x65\x65", 48}, |
178 | | { (unsigned char *) "\x01", 1} |
179 | | }, |
180 | | { |
181 | | { (unsigned char *) "\x2B\x24\x03\x03\x02\x08\x01\x01\x0E", 9}, // brainpoolP512t1 |
182 | | { (unsigned char *) "\xAA\xDD\x9D\xB8\xDB\xE9\xC4\x8B\x3F\xD4\xE6\xAE\x33\xC9\xFC\x07\xCB\x30\x8D\xB3\xB3\xC9\xD2\x0E\xD6\x63\x9C\xCA\x70\x33\x08\x71\x7D\x4D\x9B\x00\x9B\xC6\x68\x42\xAE\xCD\xA1\x2A\xE6\xA3\x80\xE6\x28\x81\xFF\x2F\x2D\x82\xC6\x85\x28\xAA\x60\x56\x58\x3A\x48\xF3", 64}, |
183 | | { (unsigned char *) "\xAA\xDD\x9D\xB8\xDB\xE9\xC4\x8B\x3F\xD4\xE6\xAE\x33\xC9\xFC\x07\xCB\x30\x8D\xB3\xB3\xC9\xD2\x0E\xD6\x63\x9C\xCA\x70\x33\x08\x71\x7D\x4D\x9B\x00\x9B\xC6\x68\x42\xAE\xCD\xA1\x2A\xE6\xA3\x80\xE6\x28\x81\xFF\x2F\x2D\x82\xC6\x85\x28\xAA\x60\x56\x58\x3A\x48\xF0", 64}, |
184 | | { (unsigned char *) "\x7C\xBB\xBC\xF9\x44\x1C\xFA\xB7\x6E\x18\x90\xE4\x68\x84\xEA\xE3\x21\xF7\x0C\x0B\xCB\x49\x81\x52\x78\x97\x50\x4B\xEC\x3E\x36\xA6\x2B\xCD\xFA\x23\x04\x97\x65\x40\xF6\x45\x00\x85\xF2\xDA\xE1\x45\xC2\x25\x53\xB4\x65\x76\x36\x89\x18\x0E\xA2\x57\x18\x67\x42\x3E", 64}, |
185 | | { (unsigned char *) "\x04\x64\x0E\xCE\x5C\x12\x78\x87\x17\xB9\xC1\xBA\x06\xCB\xC2\xA6\xFE\xBA\x85\x84\x24\x58\xC5\x6D\xDE\x9D\xB1\x75\x8D\x39\xC0\x31\x3D\x82\xBA\x51\x73\x5C\xDB\x3E\xA4\x99\xAA\x77\xA7\xD6\x94\x3A\x64\xF7\xA3\xF2\x5F\xE2\x6F\x06\xB5\x1B\xAA\x26\x96\xFA\x90\x35\xDA\x5B\x53\x4B\xD5\x95\xF5\xAF\x0F\xA2\xC8\x92\x37\x6C\x84\xAC\xE1\xBB\x4E\x30\x19\xB7\x16\x34\xC0\x11\x31\x15\x9C\xAE\x03\xCE\xE9\xD9\x93\x21\x84\xBE\xEF\x21\x6B\xD7\x1D\xF2\xDA\xDF\x86\xA6\x27\x30\x6E\xCF\xF9\x6D\xBB\x8B\xAC\xE1\x98\xB6\x1E\x00\xF8\xB3\x32", 129}, |
186 | | { (unsigned char *) "\xAA\xDD\x9D\xB8\xDB\xE9\xC4\x8B\x3F\xD4\xE6\xAE\x33\xC9\xFC\x07\xCB\x30\x8D\xB3\xB3\xC9\xD2\x0E\xD6\x63\x9C\xCA\x70\x33\x08\x70\x55\x3E\x5C\x41\x4C\xA9\x26\x19\x41\x86\x61\x19\x7F\xAC\x10\x47\x1D\xB1\xD3\x81\x08\x5D\xDA\xDD\xB5\x87\x96\x82\x9C\xA9\x00\x69", 64}, |
187 | | { (unsigned char *) "\x01", 1} |
188 | | }, |
189 | | { |
190 | | { (unsigned char *) "\x2B\x81\x04\x00\x1F", 5}, // secp192k1 |
191 | | { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xEE\x37", 24}, |
192 | | { (unsigned char *) "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 24}, |
193 | | { (unsigned char *) "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x03", 24}, |
194 | | { (unsigned char *) "\x04\xDB\x4F\xF1\x0E\xC0\x57\xE9\xAE\x26\xB0\x7D\x02\x80\xB7\xF4\x34\x1D\xA5\xD1\xB1\xEA\xE0\x6C\x7D\x9B\x2F\x2F\x6D\x9C\x56\x28\xA7\x84\x41\x63\xD0\x15\xBE\x86\x34\x40\x82\xAA\x88\xD9\x5E\x2F\x9D", 49}, |
195 | | { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\x26\xF2\xFC\x17\x0F\x69\x46\x6A\x74\xDE\xFD\x8D", 24}, |
196 | | { (unsigned char *) "\x01", 1} |
197 | | }, |
198 | | { |
199 | | { (unsigned char *) "\x2B\x81\x04\x00\x0A", 5}, // secp256k1 |
200 | | { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xFF\xFF\xFC\x2F", 32}, |
201 | | { (unsigned char *) "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 32}, |
202 | | { (unsigned char *) "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x07", 32}, |
203 | | { (unsigned char *) "\x04\x79\xBE\x66\x7E\xF9\xDC\xBB\xAC\x55\xA0\x62\x95\xCE\x87\x0B\x07\x02\x9B\xFC\xDB\x2D\xCE\x28\xD9\x59\xF2\x81\x5B\x16\xF8\x17\x98\x48\x3A\xDA\x77\x26\xA3\xC4\x65\x5D\xA4\xFB\xFC\x0E\x11\x08\xA8\xFD\x17\xB4\x48\xA6\x85\x54\x19\x9C\x47\xD0\x8F\xFB\x10\xD4\xB8", 65}, |
204 | | { (unsigned char *) "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFE\xBA\xAE\xDC\xE6\xAF\x48\xA0\x3B\xBF\xD2\x5E\x8C\xD0\x36\x41\x41", 32}, |
205 | | { (unsigned char *) "\x01", 1} |
206 | | }, |
207 | | { |
208 | | { NULL, 0}, |
209 | | { NULL, 0}, |
210 | | { NULL, 0}, |
211 | | { NULL, 0}, |
212 | | { NULL, 0}, |
213 | | { NULL, 0}, |
214 | | { NULL, 0} |
215 | | } |
216 | | }; |
217 | | // clang-format on |
218 | | |
219 | 118 | #define C_ASN1_CVC_PUBKEY_SIZE 10 |
220 | | static const struct sc_asn1_entry c_asn1_cvc_pubkey[C_ASN1_CVC_PUBKEY_SIZE] = { |
221 | | { "publicKeyOID", SC_ASN1_OBJECT, SC_ASN1_UNI | SC_ASN1_OBJECT, 0, NULL, NULL }, |
222 | | { "primeOrModulus", SC_ASN1_OCTET_STRING, SC_ASN1_CTX | 1, SC_ASN1_OPTIONAL | SC_ASN1_ALLOC, NULL, NULL }, |
223 | | { "coefficientAorExponent", SC_ASN1_OCTET_STRING, SC_ASN1_CTX | 2, SC_ASN1_OPTIONAL | SC_ASN1_ALLOC, NULL, NULL }, |
224 | | { "coefficientB", SC_ASN1_OCTET_STRING, SC_ASN1_CTX | 3, SC_ASN1_OPTIONAL | SC_ASN1_ALLOC, NULL, NULL }, |
225 | | { "basePointG", SC_ASN1_OCTET_STRING, SC_ASN1_CTX | 4, SC_ASN1_OPTIONAL | SC_ASN1_ALLOC, NULL, NULL }, |
226 | | { "order", SC_ASN1_OCTET_STRING, SC_ASN1_CTX | 5, SC_ASN1_OPTIONAL | SC_ASN1_ALLOC, NULL, NULL }, |
227 | | { "publicPoint", SC_ASN1_OCTET_STRING, SC_ASN1_CTX | 6, SC_ASN1_OPTIONAL | SC_ASN1_ALLOC, NULL, NULL }, |
228 | | { "cofactor", SC_ASN1_OCTET_STRING, SC_ASN1_CTX | 7, SC_ASN1_OPTIONAL | SC_ASN1_ALLOC, NULL, NULL }, |
229 | | { "modulusSize", SC_ASN1_INTEGER, SC_ASN1_UNI | SC_ASN1_INTEGER, SC_ASN1_OPTIONAL, NULL, NULL }, |
230 | | { NULL, 0, 0, 0, NULL, NULL } |
231 | | }; |
232 | | |
233 | 118 | #define C_ASN1_CVC_BODY_SIZE 5 |
234 | | static const struct sc_asn1_entry c_asn1_cvc_body[C_ASN1_CVC_BODY_SIZE] = { |
235 | | { "certificateProfileIdentifier", SC_ASN1_INTEGER, SC_ASN1_APP | 0x1F29, 0, NULL, NULL }, |
236 | | { "certificationAuthorityReference", SC_ASN1_PRINTABLESTRING, SC_ASN1_APP | 2, SC_ASN1_OPTIONAL, NULL, NULL }, |
237 | | { "publicKey", SC_ASN1_STRUCT, SC_ASN1_CONS | SC_ASN1_APP | 0x1F49, 0, NULL, NULL }, |
238 | | { "certificateHolderReference", SC_ASN1_PRINTABLESTRING, SC_ASN1_APP | 0x1F20, 0, NULL, NULL }, |
239 | | { NULL, 0, 0, 0, NULL, NULL } |
240 | | }; |
241 | | |
242 | 118 | #define C_ASN1_CVCERT_SIZE 3 |
243 | | static const struct sc_asn1_entry c_asn1_cvcert[C_ASN1_CVCERT_SIZE] = { |
244 | | { "certificateBody", SC_ASN1_STRUCT, SC_ASN1_CONS | SC_ASN1_APP | 0x1F4E, 0, NULL, NULL }, |
245 | | { "signature", SC_ASN1_OCTET_STRING, SC_ASN1_APP | 0x1F37, SC_ASN1_ALLOC, NULL, NULL }, |
246 | | { NULL, 0, 0, 0, NULL, NULL } |
247 | | }; |
248 | | |
249 | | #define C_ASN1_CVC_SIZE 2 |
250 | | static const struct sc_asn1_entry c_asn1_cvc[C_ASN1_CVC_SIZE] = { |
251 | | { "certificate", SC_ASN1_STRUCT, SC_ASN1_CONS | SC_ASN1_APP | 0x1F21, 0, NULL, NULL }, |
252 | | { NULL, 0, 0, 0, NULL, NULL } |
253 | | }; |
254 | | |
255 | 118 | #define C_ASN1_AUTHREQ_SIZE 4 |
256 | | static const struct sc_asn1_entry c_asn1_authreq[C_ASN1_AUTHREQ_SIZE] = { |
257 | | { "certificate", SC_ASN1_STRUCT, SC_ASN1_CONS | SC_ASN1_APP | 0x1F21, 0, NULL, NULL }, |
258 | | { "outerCAR", SC_ASN1_PRINTABLESTRING, SC_ASN1_APP | 2, 0, NULL, NULL }, |
259 | | { "signature", SC_ASN1_OCTET_STRING, SC_ASN1_APP | 0x1F37, SC_ASN1_ALLOC, NULL, NULL }, |
260 | | { NULL, 0, 0, 0, NULL, NULL } |
261 | | }; |
262 | | |
263 | | #define C_ASN1_REQ_SIZE 2 |
264 | | static const struct sc_asn1_entry c_asn1_req[C_ASN1_REQ_SIZE] = { |
265 | | { "authenticatedrequest", SC_ASN1_STRUCT, SC_ASN1_CONS | SC_ASN1_APP | 7, 0, NULL, NULL }, |
266 | | { NULL, 0, 0, 0, NULL, NULL } |
267 | | }; |
268 | | |
269 | | struct sc_object_id sc_hsm_public_key_oid = { |
270 | | {1, 3, 6, 1, 4, 1, 24991, 4, 3, 1, -1} |
271 | | }; |
272 | | |
273 | | #define C_ASN1_SC_HSM_PKA_NEW_SIZE 5 |
274 | | static const struct sc_asn1_entry c_asn1_sc_hsm_pka_new_format[C_ASN1_SC_HSM_PKA_NEW_SIZE] = { |
275 | | { "oid", SC_ASN1_OBJECT, SC_ASN1_TAG_UNIVERSAL | SC_ASN1_TAG_OBJECT, 0, NULL, NULL }, |
276 | | { "dicaCVC", SC_ASN1_STRUCT, SC_ASN1_CONS | SC_ASN1_APP | 1, 0, NULL, NULL }, |
277 | | { "deviceCVC", SC_ASN1_STRUCT, SC_ASN1_CONS | SC_ASN1_APP | 2, 0, NULL, NULL }, |
278 | | { "publicKey", SC_ASN1_STRUCT, SC_ASN1_CONS | SC_ASN1_APP | 3, 0, NULL, NULL }, |
279 | | { NULL, 0, 0, 0, NULL, NULL } |
280 | | }; |
281 | | |
282 | | #define C_ASN1_SC_HSM_PKA_OLD_SIZE 4 |
283 | | static const struct sc_asn1_entry c_asn1_sc_hsm_pka_old_format[C_ASN1_SC_HSM_PKA_OLD_SIZE] = { |
284 | | { "publicKey", SC_ASN1_STRUCT, SC_ASN1_CONS | SC_ASN1_APP | 7, 0, NULL, NULL }, |
285 | | { "deviceCVCert", SC_ASN1_STRUCT, SC_ASN1_CONS | SC_ASN1_APP | 0x1F21, 0, NULL, NULL }, |
286 | | { "dicaCVCert", SC_ASN1_STRUCT, SC_ASN1_CONS | SC_ASN1_APP | 0x1F21, 0, NULL, NULL }, |
287 | | { NULL, 0, 0, 0, NULL, NULL } |
288 | | }; |
289 | | |
290 | | |
291 | | static int read_file(sc_pkcs15_card_t * p15card, u8 fid[2], |
292 | | u8 *efbin, size_t *len, int optional) |
293 | 58 | { |
294 | 58 | sc_path_t path; |
295 | 58 | int r; |
296 | | |
297 | 58 | sc_path_set(&path, SC_PATH_TYPE_FILE_ID, fid, 2, 0, 0); |
298 | | /* look this up with our AID */ |
299 | 58 | path.aid = sc_hsm_aid; |
300 | | /* we don't have a pre-known size of the file */ |
301 | 58 | path.count = -1; |
302 | 58 | if (!p15card->opts.use_file_cache || !efbin |
303 | 58 | || SC_SUCCESS != sc_pkcs15_read_cached_file(p15card, &path, &efbin, len)) { |
304 | | /* avoid re-selection of SC-HSM */ |
305 | 58 | path.aid.len = 0; |
306 | 58 | r = sc_select_file(p15card->card, &path, NULL); |
307 | 58 | if (r < 0) { |
308 | 20 | sc_log(p15card->card->ctx, "Could not select EF"); |
309 | 38 | } else { |
310 | 38 | r = sc_read_binary(p15card->card, 0, efbin, *len, 0); |
311 | 38 | } |
312 | | |
313 | 58 | if (r < 0) { |
314 | 29 | sc_log(p15card->card->ctx, "Could not read EF"); |
315 | 29 | if (!optional) { |
316 | 0 | return r; |
317 | 0 | } |
318 | | /* optional files are saved as empty files to avoid card |
319 | | * transactions. Parsing the file's data will reveal that they were |
320 | | * missing. */ |
321 | 29 | *len = 0; |
322 | 29 | } else { |
323 | 29 | *len = r; |
324 | 29 | } |
325 | | |
326 | 58 | if (p15card->opts.use_file_cache) { |
327 | | /* save this with our AID */ |
328 | 0 | path.aid = sc_hsm_aid; |
329 | 0 | sc_pkcs15_cache_file(p15card, &path, efbin, *len); |
330 | 0 | } |
331 | 58 | } |
332 | | |
333 | 58 | return SC_SUCCESS; |
334 | 58 | } |
335 | | |
336 | | static void fixup_cvc_printable_string_lengths(sc_cvc_t *cvc) |
337 | 0 | { |
338 | | /* SC_ASN1_PRINTABLESTRING adds 1 for the null-terminator */ |
339 | 0 | if (cvc->chrLen > 0) { |
340 | 0 | cvc->chrLen--; |
341 | 0 | } |
342 | 0 | if (cvc->carLen > 0) { |
343 | 0 | cvc->carLen--; |
344 | 0 | } |
345 | 0 | if (cvc->outerCARLen > 0) { |
346 | 0 | cvc->outerCARLen--; |
347 | 0 | } |
348 | 0 | } |
349 | | |
350 | | /* |
351 | | * Sets up asn1_cvcert to point to asn1_cvc_body, asn1_cvc_pubkey, and |
352 | | * cvc. When sc_asn1_decode is called on asn1_cvcert, it will populate fields |
353 | | * in cvc. |
354 | | * |
355 | | * @param asn1_cvcert: unpopulated array with len matching c_asn1_cvcert |
356 | | * @param asn1_cvc_cert: unpopulated array with len matching c_asn1_cvc_body |
357 | | * @param asn1_cvc_pubkey: unpopulated array matching c_asn1_cvc_pubkey |
358 | | * @param cvc: non NULL cvc struct |
359 | | */ |
360 | | static int sc_pkcs15emu_sc_hsm_format_asn1_cvcert( |
361 | | struct sc_asn1_entry *asn1_cvcert, size_t asn1_cvcert_len, |
362 | | struct sc_asn1_entry *asn1_cvc_body, size_t asn1_cvc_body_len, |
363 | | struct sc_asn1_entry *asn1_cvc_pubkey, size_t asn1_cvc_pubkey_len, |
364 | | sc_cvc_t *cvc) |
365 | 59 | { |
366 | 59 | if ((asn1_cvc_pubkey_len < C_ASN1_CVC_PUBKEY_SIZE) || |
367 | 59 | (asn1_cvc_body_len < C_ASN1_CVC_BODY_SIZE) || |
368 | 59 | (asn1_cvcert_len < C_ASN1_CVCERT_SIZE)) { |
369 | 0 | return SC_ERROR_BUFFER_TOO_SMALL; |
370 | 0 | } |
371 | | |
372 | 59 | sc_copy_asn1_entry(c_asn1_cvc_pubkey, asn1_cvc_pubkey); |
373 | 59 | sc_copy_asn1_entry(c_asn1_cvc_body, asn1_cvc_body); |
374 | 59 | sc_copy_asn1_entry(c_asn1_cvcert, asn1_cvcert); |
375 | | |
376 | 59 | sc_format_asn1_entry(asn1_cvc_pubkey , &cvc->pukoid, NULL, 0); |
377 | 59 | sc_format_asn1_entry(asn1_cvc_pubkey + 1, &cvc->primeOrModulus, &cvc->primeOrModuluslen, 0); |
378 | 59 | sc_format_asn1_entry(asn1_cvc_pubkey + 2, &cvc->coefficientAorExponent, &cvc->coefficientAorExponentlen, 0); |
379 | 59 | sc_format_asn1_entry(asn1_cvc_pubkey + 3, &cvc->coefficientB, &cvc->coefficientBlen, 0); |
380 | 59 | sc_format_asn1_entry(asn1_cvc_pubkey + 4, &cvc->basePointG, &cvc->basePointGlen, 0); |
381 | 59 | sc_format_asn1_entry(asn1_cvc_pubkey + 5, &cvc->order, &cvc->orderlen, 0); |
382 | 59 | sc_format_asn1_entry(asn1_cvc_pubkey + 6, &cvc->publicPoint, &cvc->publicPointlen, 0); |
383 | 59 | sc_format_asn1_entry(asn1_cvc_pubkey + 7, &cvc->cofactor, &cvc->cofactorlen, 0); |
384 | 59 | sc_format_asn1_entry(asn1_cvc_pubkey + 8, &cvc->modulusSize, NULL, 0); |
385 | | |
386 | 59 | sc_format_asn1_entry(asn1_cvc_body , &cvc->cpi, NULL, 0); |
387 | 59 | cvc->carLen = sizeof(cvc->car); |
388 | 59 | sc_format_asn1_entry(asn1_cvc_body + 1, &cvc->car, &cvc->carLen, 0); |
389 | 59 | sc_format_asn1_entry(asn1_cvc_body + 2, asn1_cvc_pubkey, NULL, 0); |
390 | 59 | cvc->chrLen = sizeof(cvc->chr); |
391 | 59 | sc_format_asn1_entry(asn1_cvc_body + 3, &cvc->chr, &cvc->chrLen, 0); |
392 | | |
393 | 59 | sc_format_asn1_entry(asn1_cvcert , asn1_cvc_body, NULL, 0); |
394 | 59 | sc_format_asn1_entry(asn1_cvcert + 1, &cvc->signature, &cvc->signatureLen, 0); |
395 | 59 | return SC_SUCCESS; |
396 | 59 | } |
397 | | |
398 | | /* |
399 | | * Sets up asn1_req to point to asn1_authreq, which points to asn1_cvcert and |
400 | | * cvc |
401 | | * When sc_asn1_decode is called on asn1_authreq, it will populate fields |
402 | | * in cvc and asn1_cvcert |
403 | | * |
404 | | * @param asn1_authreq: unpopulated array with len matching c_asn1_req |
405 | | * @param asn1_authreq: unpopulated array with len matching c_asn1_authreq |
406 | | * @param asn1_cvcert: already-initialized array matching c_asn1_cvcert |
407 | | * |
408 | | */ |
409 | | static int sc_pkcs15emu_sc_hsm_format_asn1_req( |
410 | | struct sc_asn1_entry *asn1_authreq, size_t asn1_authreq_len, |
411 | | struct sc_asn1_entry *asn1_cvcert, |
412 | | sc_cvc_t *cvc) |
413 | 59 | { |
414 | 59 | if (asn1_authreq_len < C_ASN1_AUTHREQ_SIZE) { |
415 | 0 | return SC_ERROR_BUFFER_TOO_SMALL; |
416 | 0 | } |
417 | | |
418 | 59 | sc_copy_asn1_entry(c_asn1_authreq, asn1_authreq); |
419 | | |
420 | 59 | sc_format_asn1_entry(asn1_authreq , asn1_cvcert, NULL, 0); |
421 | 59 | cvc->outerCARLen = sizeof(cvc->outer_car); |
422 | 59 | sc_format_asn1_entry(asn1_authreq + 1, &cvc->outer_car, &cvc->outerCARLen, 0); |
423 | 59 | sc_format_asn1_entry(asn1_authreq + 2, &cvc->outerSignature, &cvc->outerSignatureLen, 0); |
424 | 59 | return SC_SUCCESS; |
425 | 59 | } |
426 | | |
427 | | /* |
428 | | * Decode a card verifiable certificate as defined in TR-03110. |
429 | | */ |
430 | | int sc_pkcs15emu_sc_hsm_decode_cvc(sc_pkcs15_card_t * p15card, |
431 | | const u8 ** buf, size_t *buflen, |
432 | | sc_cvc_t *cvc) |
433 | 59 | { |
434 | 59 | sc_card_t *card = p15card->card; |
435 | 59 | struct sc_asn1_entry asn1_req[C_ASN1_REQ_SIZE]; |
436 | 59 | struct sc_asn1_entry asn1_authreq[C_ASN1_AUTHREQ_SIZE]; |
437 | 59 | struct sc_asn1_entry asn1_cvc[C_ASN1_CVC_SIZE]; |
438 | 59 | struct sc_asn1_entry asn1_cvcert[C_ASN1_CVCERT_SIZE]; |
439 | 59 | struct sc_asn1_entry asn1_cvc_body[C_ASN1_CVC_BODY_SIZE]; |
440 | 59 | struct sc_asn1_entry asn1_cvc_pubkey[C_ASN1_CVC_PUBKEY_SIZE]; |
441 | 59 | unsigned int cla = 0, tag = 0; |
442 | 59 | size_t taglen; |
443 | 59 | const u8 *tbuf; |
444 | 59 | int r; |
445 | | |
446 | 59 | memset(cvc, 0, sizeof(*cvc)); |
447 | 59 | sc_copy_asn1_entry(c_asn1_req, asn1_req); |
448 | 59 | sc_copy_asn1_entry(c_asn1_cvc, asn1_cvc); |
449 | | |
450 | 59 | r = sc_pkcs15emu_sc_hsm_format_asn1_cvcert( |
451 | 59 | asn1_cvcert, C_ASN1_CVCERT_SIZE, |
452 | 59 | asn1_cvc_body, C_ASN1_CVC_BODY_SIZE, |
453 | 59 | asn1_cvc_pubkey, C_ASN1_CVC_PUBKEY_SIZE, |
454 | 59 | cvc); |
455 | 59 | LOG_TEST_RET(card->ctx, r, "sc_asn1_entry array too small"); |
456 | | |
457 | 59 | sc_format_asn1_entry(asn1_cvc, asn1_cvcert, NULL, 0); |
458 | | |
459 | 59 | r = sc_pkcs15emu_sc_hsm_format_asn1_req( |
460 | 59 | asn1_authreq, C_ASN1_AUTHREQ_SIZE, |
461 | 59 | asn1_cvcert, cvc); |
462 | 59 | LOG_TEST_RET(card->ctx, r, "sc_asn1_entry array too small"); |
463 | | |
464 | 59 | sc_format_asn1_entry(asn1_req, asn1_authreq, NULL, 0); |
465 | | |
466 | | /* sc_asn1_print_tags(*buf, *buflen); */ |
467 | | |
468 | 59 | tbuf = *buf; |
469 | 59 | r = sc_asn1_read_tag(&tbuf, *buflen, &cla, &tag, &taglen); |
470 | 59 | LOG_TEST_RET(card->ctx, r, "Could not decode card verifiable certificate"); |
471 | | |
472 | | /* Determine if we deal with an authenticated request, plain request or certificate */ |
473 | 22 | if ((cla == (SC_ASN1_TAG_APPLICATION|SC_ASN1_TAG_CONSTRUCTED)) && (tag == 7)) { |
474 | 3 | r = sc_asn1_decode(card->ctx, asn1_req, *buf, *buflen, buf, buflen); |
475 | 19 | } else { |
476 | 19 | r = sc_asn1_decode(card->ctx, asn1_cvc, *buf, *buflen, buf, buflen); |
477 | 19 | } |
478 | | |
479 | 22 | LOG_TEST_RET(card->ctx, r, "Could not decode card verifiable certificate"); |
480 | | |
481 | 0 | fixup_cvc_printable_string_lengths(cvc); |
482 | |
|
483 | 0 | LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); |
484 | 0 | } |
485 | | |
486 | | struct sc_asn1_cvc_format { |
487 | | struct sc_asn1_entry asn1_cvc[C_ASN1_CVC_SIZE]; |
488 | | struct sc_asn1_entry asn1_cvcert[C_ASN1_CVCERT_SIZE]; |
489 | | struct sc_asn1_entry asn1_cvc_body[C_ASN1_CVC_BODY_SIZE]; |
490 | | struct sc_asn1_entry asn1_cvc_pubkey[C_ASN1_CVC_PUBKEY_SIZE]; |
491 | | }; |
492 | | |
493 | | struct sc_asn1_sc_hsm_pka_callback_arg { |
494 | | sc_context_t *ctx; |
495 | | struct sc_asn1_entry *next_entry; |
496 | | sc_cvc_pka_component_t *component; |
497 | | }; |
498 | | |
499 | | |
500 | | struct sc_asn1_sc_hsm_pka_data { |
501 | | struct sc_asn1_entry asn1_public_key_req[C_ASN1_REQ_SIZE]; |
502 | | struct sc_asn1_entry asn1_public_key_authreq[C_ASN1_AUTHREQ_SIZE]; |
503 | | struct sc_asn1_cvc_format asn1_public_key_cvc; |
504 | | struct sc_asn1_cvc_format asn1_device_cvc; |
505 | | struct sc_asn1_cvc_format asn1_dica_cvc; |
506 | | struct sc_asn1_sc_hsm_pka_callback_arg public_key_req_arg; |
507 | | struct sc_asn1_sc_hsm_pka_callback_arg device_arg; |
508 | | struct sc_asn1_sc_hsm_pka_callback_arg dica_arg; |
509 | | }; |
510 | | |
511 | | struct sc_asn1_sc_hsm_pka_new_format { |
512 | | struct sc_asn1_entry seq[C_ASN1_SC_HSM_PKA_NEW_SIZE]; |
513 | | struct sc_asn1_sc_hsm_pka_data data; |
514 | | struct sc_object_id oid; |
515 | | }; |
516 | | |
517 | | struct sc_asn1_sc_hsm_pka_old_format { |
518 | | struct sc_asn1_entry seq[C_ASN1_SC_HSM_PKA_OLD_SIZE]; |
519 | | struct sc_asn1_sc_hsm_pka_data data; |
520 | | }; |
521 | | |
522 | | /* |
523 | | * Saves the current pointer then continues to decode |
524 | | */ |
525 | | static int sc_asn1_sc_hsm_pka_set_ptr_callback( |
526 | | sc_context_t *nctx, void *arg, const u8 *obj, |
527 | | size_t objlen, int depth) |
528 | 0 | { |
529 | 0 | struct sc_asn1_sc_hsm_pka_callback_arg *carg = arg; |
530 | |
|
531 | 0 | carg->component->ptr = obj; |
532 | 0 | carg->component->len = objlen; |
533 | |
|
534 | 0 | return sc_asn1_decode(carg->ctx, carg->next_entry, obj, objlen, NULL, NULL); |
535 | 0 | } |
536 | | |
537 | | static int sc_asn1_sc_hsm_pka_data_init(sc_context_t *ctx, |
538 | | struct sc_asn1_sc_hsm_pka_data *data, |
539 | | sc_cvc_pka_t *pka) |
540 | 0 | { |
541 | 0 | int r; |
542 | |
|
543 | 0 | data->public_key_req_arg.ctx = ctx; |
544 | 0 | data->device_arg.ctx = ctx; |
545 | 0 | data->dica_arg.ctx = ctx; |
546 | | |
547 | | /* public key info is in an authenticatedrequest (0x67) */ |
548 | 0 | r = sc_pkcs15emu_sc_hsm_format_asn1_cvcert( |
549 | 0 | data->asn1_public_key_cvc.asn1_cvcert, C_ASN1_CVCERT_SIZE, |
550 | 0 | data->asn1_public_key_cvc.asn1_cvc_body, C_ASN1_CVC_BODY_SIZE, |
551 | 0 | data->asn1_public_key_cvc.asn1_cvc_pubkey, C_ASN1_CVC_PUBKEY_SIZE, |
552 | 0 | &pka->public_key_req.cvc); |
553 | 0 | LOG_TEST_RET(ctx, r, "sc_asn1_entry too small"); |
554 | | |
555 | 0 | r = sc_pkcs15emu_sc_hsm_format_asn1_req( |
556 | 0 | data->asn1_public_key_authreq, C_ASN1_AUTHREQ_SIZE, |
557 | 0 | data->asn1_public_key_cvc.asn1_cvcert, |
558 | 0 | &pka->public_key_req.cvc); |
559 | 0 | LOG_TEST_RET(ctx, r, "sc_asn1_entry too small"); |
560 | | |
561 | | /* |
562 | | * insert a callback between req and authreq |
563 | | * the HSM expects the contents of the 0x67 authenticatedrequest tag (not |
564 | | * including the 0x67 tag itself) |
565 | | */ |
566 | 0 | sc_copy_asn1_entry(c_asn1_req, data->asn1_public_key_req); |
567 | 0 | data->asn1_public_key_req[0].type = SC_ASN1_CALLBACK; |
568 | 0 | data->public_key_req_arg.component = &pka->public_key_req; |
569 | 0 | data->public_key_req_arg.next_entry = data->asn1_public_key_authreq; |
570 | 0 | sc_format_asn1_entry(data->asn1_public_key_req, |
571 | 0 | sc_asn1_sc_hsm_pka_set_ptr_callback, |
572 | 0 | &data->public_key_req_arg, 0); |
573 | | |
574 | | /* device CVC is a certificate (0x7F21) */ |
575 | 0 | r = sc_pkcs15emu_sc_hsm_format_asn1_cvcert( |
576 | 0 | data->asn1_device_cvc.asn1_cvcert, C_ASN1_CVCERT_SIZE, |
577 | 0 | data->asn1_device_cvc.asn1_cvc_body, C_ASN1_CVC_BODY_SIZE, |
578 | 0 | data->asn1_device_cvc.asn1_cvc_pubkey, C_ASN1_CVC_PUBKEY_SIZE, |
579 | 0 | &pka->device.cvc); |
580 | 0 | LOG_TEST_RET(ctx, r, "sc_asn1_entry too small"); |
581 | | |
582 | | /* |
583 | | * insert a callback between asn1_cvc and asn1_cvcert |
584 | | * the HSM expects the contents of the 0x7F21 CVC tag (not including the |
585 | | * 0x7F21 tag itself) |
586 | | */ |
587 | 0 | sc_copy_asn1_entry(c_asn1_cvc, data->asn1_device_cvc.asn1_cvc); |
588 | 0 | data->asn1_device_cvc.asn1_cvc[0].type = SC_ASN1_CALLBACK; |
589 | 0 | data->device_arg.component = &pka->device; |
590 | 0 | data->device_arg.next_entry = data->asn1_device_cvc.asn1_cvcert; |
591 | 0 | sc_format_asn1_entry(data->asn1_device_cvc.asn1_cvc, |
592 | 0 | sc_asn1_sc_hsm_pka_set_ptr_callback, |
593 | 0 | &data->device_arg, 0); |
594 | | |
595 | | /* device issuer CA CVC is a certificate (0x7F21) */ |
596 | 0 | r = sc_pkcs15emu_sc_hsm_format_asn1_cvcert( |
597 | 0 | data->asn1_dica_cvc.asn1_cvcert, C_ASN1_CVCERT_SIZE, |
598 | 0 | data->asn1_dica_cvc.asn1_cvc_body, C_ASN1_CVC_BODY_SIZE, |
599 | 0 | data->asn1_dica_cvc.asn1_cvc_pubkey, C_ASN1_CVC_PUBKEY_SIZE, |
600 | 0 | &pka->dica.cvc); |
601 | 0 | LOG_TEST_RET(ctx, r, "sc_asn1_entry too small"); |
602 | | |
603 | | /* |
604 | | * insert a callback between asn1_cvc and asn1_cvcert |
605 | | * the HSM expects the contents of the 0x7F21 CVC tag (not including the |
606 | | * 0x7F21 tag itself) |
607 | | */ |
608 | 0 | sc_copy_asn1_entry(c_asn1_cvc, data->asn1_dica_cvc.asn1_cvc); |
609 | 0 | data->asn1_dica_cvc.asn1_cvc[0].type = SC_ASN1_CALLBACK; |
610 | 0 | data->dica_arg.component = &pka->dica; |
611 | 0 | data->dica_arg.next_entry = data->asn1_dica_cvc.asn1_cvcert; |
612 | 0 | sc_format_asn1_entry(data->asn1_dica_cvc.asn1_cvc, |
613 | 0 | sc_asn1_sc_hsm_pka_set_ptr_callback, |
614 | 0 | &data->dica_arg, 0); |
615 | 0 | return SC_SUCCESS; |
616 | 0 | } |
617 | | |
618 | | /* |
619 | | * For SmartCard HSMs, this is the older format for registering a public key |
620 | | * for public key authentication. |
621 | | * |
622 | | * @param buf: *buf should point to the first tag in the sequence |
623 | | * |
624 | | * SEQUENCE (0x30) |
625 | | * authenticatedrequest for public key details (0x67) |
626 | | * device CVC (0x7F21) |
627 | | * device issuer CA CVC (0x7F21) |
628 | | */ |
629 | | static int decode_pka_old_format(sc_pkcs15_card_t *p15card, |
630 | | const u8 **buf, size_t *buflen, |
631 | | sc_cvc_pka_t *pka) |
632 | 0 | { |
633 | 0 | int r; |
634 | 0 | sc_card_t *card; |
635 | 0 | struct sc_asn1_sc_hsm_pka_old_format *format = NULL; |
636 | |
|
637 | 0 | card = p15card->card; |
638 | |
|
639 | 0 | format = calloc(1, sizeof(*format)); |
640 | 0 | if (format == NULL) { |
641 | 0 | r = SC_ERROR_OUT_OF_MEMORY; |
642 | 0 | goto err; |
643 | 0 | } |
644 | | |
645 | 0 | r = sc_asn1_sc_hsm_pka_data_init(card->ctx, &format->data, pka); |
646 | 0 | LOG_TEST_GOTO_ERR(card->ctx, r, "sc_asn1_entry array too small"); |
647 | | |
648 | 0 | sc_copy_asn1_entry(c_asn1_sc_hsm_pka_old_format, format->seq); |
649 | 0 | format->seq[0] = format->data.asn1_public_key_req[0]; |
650 | 0 | format->seq[1] = format->data.asn1_device_cvc.asn1_cvc[0]; |
651 | 0 | format->seq[2] = format->data.asn1_dica_cvc.asn1_cvc[0]; |
652 | |
|
653 | 0 | r = sc_asn1_decode(p15card->card->ctx, format->seq, *buf, *buflen, |
654 | 0 | buf, buflen); |
655 | 0 | LOG_TEST_GOTO_ERR(card->ctx, r, |
656 | 0 | "Could not decode ASN.1 for public key file's old format"); |
657 | | |
658 | 0 | r = SC_SUCCESS; |
659 | | /* fall-through */ |
660 | |
|
661 | 0 | err: |
662 | 0 | free(format); |
663 | 0 | format = NULL; |
664 | 0 | return r; |
665 | 0 | } |
666 | | |
667 | | /* |
668 | | * For SmartCard HSMs, this is the newer format for registering a public key |
669 | | * for public key authentication. |
670 | | * |
671 | | * @param buf: *buf should point to the first tag after the sequence tag |
672 | | * |
673 | | * 1.3.6.1.4.1.24991 is the CardContact organization |
674 | | * The 4.3.1 part is from inspecting their exported public key, but it doesn't |
675 | | * seem to be publicly registered. |
676 | | * |
677 | | * SEQUENCE (0x30) |
678 | | * OID (0x6) 1.3.6.1.4.1.24991.4.3.1 |
679 | | * Application 1 (0x61) |
680 | | * device CVC (0x7F21) |
681 | | * Application 2 (0x62) |
682 | | * device issuer CA CVC (0x7F21) |
683 | | * Application 3 (0x63) |
684 | | * authenticatedrequest for public key details (0x67) |
685 | | */ |
686 | | static int decode_pka_new_format(sc_pkcs15_card_t *p15card, |
687 | | const u8 **buf, size_t *buflen, |
688 | | sc_cvc_pka_t *pka) |
689 | 0 | { |
690 | 0 | int r; |
691 | 0 | sc_card_t *card; |
692 | 0 | struct sc_asn1_sc_hsm_pka_new_format *format = NULL; |
693 | |
|
694 | 0 | card = p15card->card; |
695 | |
|
696 | 0 | format = calloc(1, sizeof(*format)); |
697 | 0 | if (format == NULL) { |
698 | 0 | r = SC_ERROR_OUT_OF_MEMORY; |
699 | 0 | goto err; |
700 | 0 | } |
701 | | |
702 | 0 | r = sc_asn1_sc_hsm_pka_data_init(card->ctx, &format->data, pka); |
703 | 0 | LOG_TEST_GOTO_ERR(card->ctx, r, "sc_asn1_entry array too small"); |
704 | | |
705 | 0 | sc_copy_asn1_entry(c_asn1_sc_hsm_pka_new_format, format->seq); |
706 | 0 | sc_format_asn1_entry(&format->seq[0], &format->oid, NULL, 0); |
707 | 0 | sc_format_asn1_entry(&format->seq[1], |
708 | 0 | format->data.asn1_dica_cvc.asn1_cvc, NULL, 0); |
709 | 0 | sc_format_asn1_entry(&format->seq[2], |
710 | 0 | format->data.asn1_device_cvc.asn1_cvc, NULL, 0); |
711 | 0 | sc_format_asn1_entry(&format->seq[3], |
712 | 0 | format->data.asn1_public_key_req, NULL, 0); |
713 | |
|
714 | 0 | r = sc_asn1_decode(p15card->card->ctx, format->seq, *buf, *buflen, |
715 | 0 | buf, buflen); |
716 | 0 | LOG_TEST_GOTO_ERR(card->ctx, r, |
717 | 0 | "Could not decode ASN.1 for public key file's new format"); |
718 | | |
719 | 0 | if (sc_compare_oid(&format->oid, &sc_hsm_public_key_oid) == 0) { |
720 | | /* sc_dump_oid uses static memory */ |
721 | 0 | sc_log(p15card->card->ctx, "OID %s did not match expected value", |
722 | 0 | sc_dump_oid(&format->oid)); |
723 | 0 | r = -1; |
724 | 0 | goto err; |
725 | 0 | } |
726 | | |
727 | 0 | r = SC_SUCCESS; |
728 | | /* fall-through */ |
729 | |
|
730 | 0 | err: |
731 | 0 | free(format); |
732 | 0 | format = NULL; |
733 | 0 | return r; |
734 | 0 | } |
735 | | |
736 | | /* |
737 | | * @param pka: will be overwritten, should be uninitialized or memset to 0 |
738 | | */ |
739 | | int sc_pkcs15emu_sc_hsm_decode_pka(sc_pkcs15_card_t *p15card, |
740 | | const u8 **buf, size_t *buflen, |
741 | | sc_cvc_pka_t *pka) |
742 | 0 | { |
743 | 0 | int r; |
744 | 0 | const u8 *curr; |
745 | 0 | const u8 *peek; |
746 | 0 | unsigned int cla, tag; |
747 | 0 | size_t taglen; |
748 | 0 | size_t currlen; |
749 | 0 | sc_card_t *card; |
750 | |
|
751 | 0 | memset(pka, 0, sizeof(*pka)); |
752 | |
|
753 | 0 | card = p15card->card; |
754 | 0 | curr = *buf; |
755 | 0 | currlen = *buflen; |
756 | | |
757 | | /* first tag should be sequence */ |
758 | 0 | r = sc_asn1_read_tag(&curr, currlen, &cla, &tag, &taglen); |
759 | 0 | LOG_TEST_GOTO_ERR(card->ctx, r, |
760 | 0 | "Could not decode first sequence tag for public key file"); |
761 | 0 | currlen = *buflen - (curr - *buf); |
762 | |
|
763 | 0 | if ((cla != (SC_ASN1_TAG_UNIVERSAL|SC_ASN1_TAG_CONSTRUCTED)) || |
764 | 0 | (tag != SC_ASN1_TAG_SEQUENCE)) { |
765 | 0 | sc_log(card->ctx, |
766 | 0 | "Expected sequence tag, but got tag %u class 0x%x", tag, cla); |
767 | 0 | r = SC_ERROR_INVALID_ASN1_OBJECT; |
768 | 0 | goto err; |
769 | 0 | } |
770 | | |
771 | | /* next tag is either OID (new format) or 0x67 (old format) */ |
772 | 0 | peek = curr; |
773 | 0 | r = sc_asn1_read_tag(&peek, currlen, &cla, &tag, &taglen); |
774 | 0 | LOG_TEST_GOTO_ERR(card->ctx, r, |
775 | 0 | "Could not decode first sequence element tag for public key file"); |
776 | | |
777 | 0 | if (tag == SC_ASN1_TAG_OBJECT) { |
778 | | /* OID means it's the new format */ |
779 | 0 | r = decode_pka_new_format(p15card, &curr, &currlen, pka); |
780 | 0 | LOG_TEST_GOTO_ERR(card->ctx, r, |
781 | 0 | "Could not decode public key file new format"); |
782 | 0 | } else if ((cla == (SC_ASN1_TAG_APPLICATION|SC_ASN1_TAG_CONSTRUCTED)) && |
783 | 0 | (tag == 7)) { |
784 | | /* |
785 | | * if it's authenticatedrequest (Application 7 / 0x67), then attempt |
786 | | * to parse the old format |
787 | | */ |
788 | 0 | r = decode_pka_old_format(p15card, &curr, &currlen, pka); |
789 | 0 | LOG_TEST_GOTO_ERR(card->ctx, r, |
790 | 0 | "Could not decode authenticatedrequest for public key file"); |
791 | 0 | } else { |
792 | 0 | sc_log(card->ctx, |
793 | 0 | "Unexpected tag %u class 0x%x for first element of sequence", |
794 | 0 | tag, cla); |
795 | 0 | r = SC_ERROR_INVALID_ASN1_OBJECT; |
796 | 0 | goto err; |
797 | 0 | } |
798 | | |
799 | 0 | fixup_cvc_printable_string_lengths(&pka->public_key_req.cvc); |
800 | 0 | fixup_cvc_printable_string_lengths(&pka->device.cvc); |
801 | 0 | fixup_cvc_printable_string_lengths(&pka->dica.cvc); |
802 | |
|
803 | 0 | *buf = curr; |
804 | 0 | *buflen = *buflen - (curr - *buf); |
805 | |
|
806 | 0 | return SC_SUCCESS; |
807 | | |
808 | 0 | err: |
809 | 0 | sc_pkcs15emu_sc_hsm_free_cvc_pka(pka); |
810 | 0 | return r; |
811 | 0 | } |
812 | | |
813 | | /* |
814 | | * Encode a card verifiable certificate as defined in TR-03110. |
815 | | */ |
816 | | int sc_pkcs15emu_sc_hsm_encode_cvc(sc_pkcs15_card_t * p15card, |
817 | | sc_cvc_t *cvc, |
818 | | u8 ** buf, size_t *buflen) |
819 | 0 | { |
820 | 0 | sc_card_t *card = p15card->card; |
821 | 0 | struct sc_asn1_entry asn1_cvc[C_ASN1_CVC_SIZE]; |
822 | 0 | struct sc_asn1_entry asn1_cvcert[C_ASN1_CVCERT_SIZE]; |
823 | 0 | struct sc_asn1_entry asn1_cvc_body[C_ASN1_CVC_BODY_SIZE]; |
824 | 0 | struct sc_asn1_entry asn1_cvc_pubkey[C_ASN1_CVC_PUBKEY_SIZE]; |
825 | 0 | int r; |
826 | |
|
827 | 0 | sc_copy_asn1_entry(c_asn1_cvc, asn1_cvc); |
828 | 0 | sc_copy_asn1_entry(c_asn1_cvcert, asn1_cvcert); |
829 | 0 | sc_copy_asn1_entry(c_asn1_cvc_body, asn1_cvc_body); |
830 | 0 | sc_copy_asn1_entry(c_asn1_cvc_pubkey, asn1_cvc_pubkey); |
831 | |
|
832 | 0 | asn1_cvc_pubkey[1].flags = SC_ASN1_OPTIONAL; |
833 | 0 | asn1_cvcert[1].flags = SC_ASN1_OPTIONAL; |
834 | |
|
835 | 0 | sc_format_asn1_entry(asn1_cvc_pubkey , &cvc->pukoid, NULL, 1); |
836 | 0 | if (cvc->primeOrModulus && (cvc->primeOrModuluslen > 0)) { |
837 | 0 | sc_format_asn1_entry(asn1_cvc_pubkey + 1, cvc->primeOrModulus, &cvc->primeOrModuluslen, 1); |
838 | 0 | } |
839 | 0 | sc_format_asn1_entry(asn1_cvc_pubkey + 2, cvc->coefficientAorExponent, &cvc->coefficientAorExponentlen, 1); |
840 | 0 | if (cvc->coefficientB && (cvc->coefficientBlen > 0)) { |
841 | 0 | sc_format_asn1_entry(asn1_cvc_pubkey + 3, cvc->coefficientB, &cvc->coefficientBlen, 1); |
842 | 0 | sc_format_asn1_entry(asn1_cvc_pubkey + 4, cvc->basePointG, &cvc->basePointGlen, 1); |
843 | 0 | sc_format_asn1_entry(asn1_cvc_pubkey + 5, cvc->order, &cvc->orderlen, 1); |
844 | 0 | if (cvc->publicPoint && (cvc->publicPointlen > 0)) { |
845 | 0 | sc_format_asn1_entry(asn1_cvc_pubkey + 6, cvc->publicPoint, &cvc->publicPointlen, 1); |
846 | 0 | } |
847 | 0 | sc_format_asn1_entry(asn1_cvc_pubkey + 7, cvc->cofactor, &cvc->cofactorlen, 1); |
848 | 0 | } |
849 | 0 | if (cvc->modulusSize > 0) { |
850 | 0 | sc_format_asn1_entry(asn1_cvc_pubkey + 8, &cvc->modulusSize, NULL, 1); |
851 | 0 | } |
852 | |
|
853 | 0 | sc_format_asn1_entry(asn1_cvc_body , &cvc->cpi, NULL, 1); |
854 | 0 | sc_format_asn1_entry(asn1_cvc_body + 1, &cvc->car, &cvc->carLen, 1); |
855 | 0 | sc_format_asn1_entry(asn1_cvc_body + 2, &asn1_cvc_pubkey, NULL, 1); |
856 | 0 | sc_format_asn1_entry(asn1_cvc_body + 3, &cvc->chr, &cvc->chrLen, 1); |
857 | |
|
858 | 0 | sc_format_asn1_entry(asn1_cvcert , &asn1_cvc_body, NULL, 1); |
859 | 0 | if (cvc->signature && (cvc->signatureLen > 0)) { |
860 | 0 | sc_format_asn1_entry(asn1_cvcert + 1, cvc->signature, &cvc->signatureLen, 1); |
861 | 0 | } |
862 | |
|
863 | 0 | sc_format_asn1_entry(asn1_cvc , &asn1_cvcert, NULL, 1); |
864 | |
|
865 | 0 | r = sc_asn1_encode(card->ctx, asn1_cvc, buf, buflen); |
866 | 0 | LOG_TEST_RET(card->ctx, r, "Could not encode card verifiable certificate"); |
867 | | |
868 | 0 | LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); |
869 | 0 | } |
870 | | |
871 | | |
872 | | |
873 | | int sc_pkcs15emu_sc_hsm_get_curve(struct ec_curve **curve, u8 *oid, size_t oidlen) |
874 | 0 | { |
875 | 0 | int i; |
876 | |
|
877 | 0 | for (i = 0; curves[i].oid.value; i++) { |
878 | 0 | if ((curves[i].oid.len == oidlen) && !memcmp(curves[i].oid.value, oid, oidlen)) { |
879 | 0 | *curve = &curves[i]; |
880 | 0 | return SC_SUCCESS; |
881 | 0 | } |
882 | 0 | } |
883 | 0 | return SC_ERROR_INVALID_DATA; |
884 | 0 | } |
885 | | |
886 | | |
887 | | |
888 | | int sc_pkcs15emu_sc_hsm_get_curve_oid(sc_cvc_t *cvc, const struct sc_lv_data **oid) |
889 | 0 | { |
890 | 0 | int i; |
891 | |
|
892 | 0 | for (i = 0; curves[i].oid.value; i++) { |
893 | 0 | if ((curves[i].prime.len == cvc->primeOrModuluslen) && |
894 | 0 | !memcmp(curves[i].prime.value, cvc->primeOrModulus, cvc->primeOrModuluslen) && |
895 | 0 | (curves[i].coefficientA.len == cvc->coefficientAorExponentlen) && |
896 | 0 | !memcmp(curves[i].coefficientA.value, |
897 | 0 | cvc->coefficientAorExponent, cvc->coefficientAorExponentlen)) { |
898 | 0 | *oid = &curves[i].oid; |
899 | 0 | return SC_SUCCESS; |
900 | 0 | } |
901 | 0 | } |
902 | 0 | return SC_ERROR_INVALID_DATA; |
903 | 0 | } |
904 | | |
905 | | |
906 | | |
907 | | static int sc_pkcs15emu_sc_hsm_get_rsa_public_key(struct sc_context *ctx, sc_cvc_t *cvc, struct sc_pkcs15_pubkey *pubkey) |
908 | 0 | { |
909 | 0 | pubkey->algorithm = SC_ALGORITHM_RSA; |
910 | |
|
911 | 0 | pubkey->alg_id = (struct sc_algorithm_id *)calloc(1, sizeof(struct sc_algorithm_id)); |
912 | 0 | if (!pubkey->alg_id) |
913 | 0 | return SC_ERROR_OUT_OF_MEMORY; |
914 | | |
915 | 0 | pubkey->alg_id->algorithm = SC_ALGORITHM_RSA; |
916 | |
|
917 | 0 | pubkey->u.rsa.modulus.len = cvc->primeOrModuluslen; |
918 | 0 | pubkey->u.rsa.modulus.data = malloc(pubkey->u.rsa.modulus.len); |
919 | 0 | pubkey->u.rsa.exponent.len = cvc->coefficientAorExponentlen; |
920 | 0 | pubkey->u.rsa.exponent.data = malloc(pubkey->u.rsa.exponent.len); |
921 | 0 | if (!pubkey->u.rsa.modulus.data || !pubkey->u.rsa.exponent.data) { |
922 | 0 | free(pubkey->u.rsa.modulus.data); |
923 | 0 | free(pubkey->u.rsa.exponent.data); |
924 | 0 | free(pubkey->alg_id); |
925 | 0 | return SC_ERROR_OUT_OF_MEMORY; |
926 | 0 | } |
927 | | |
928 | 0 | memcpy(pubkey->u.rsa.exponent.data, cvc->coefficientAorExponent, pubkey->u.rsa.exponent.len); |
929 | 0 | memcpy(pubkey->u.rsa.modulus.data, cvc->primeOrModulus, pubkey->u.rsa.modulus.len); |
930 | |
|
931 | 0 | return SC_SUCCESS; |
932 | 0 | } |
933 | | |
934 | | |
935 | | |
936 | | static int sc_pkcs15emu_sc_hsm_get_ec_public_key(struct sc_context *ctx, sc_cvc_t *cvc, struct sc_pkcs15_pubkey *pubkey) |
937 | 0 | { |
938 | 0 | struct sc_ec_parameters *ecp; |
939 | 0 | const struct sc_lv_data *oid; |
940 | 0 | int r; |
941 | |
|
942 | 0 | pubkey->algorithm = SC_ALGORITHM_EC; |
943 | |
|
944 | 0 | r = sc_pkcs15emu_sc_hsm_get_curve_oid(cvc, &oid); |
945 | 0 | if (r != SC_SUCCESS) |
946 | 0 | return r; |
947 | | |
948 | 0 | ecp = calloc(1, sizeof(struct sc_ec_parameters)); |
949 | 0 | if (!ecp) |
950 | 0 | return SC_ERROR_OUT_OF_MEMORY; |
951 | | |
952 | 0 | ecp->der.len = oid->len + 2; |
953 | 0 | ecp->der.value = calloc(1, ecp->der.len); |
954 | 0 | if (!ecp->der.value) { |
955 | 0 | free(ecp); |
956 | 0 | return SC_ERROR_OUT_OF_MEMORY; |
957 | 0 | } |
958 | | |
959 | 0 | *(ecp->der.value + 0) = 0x06; |
960 | 0 | *(ecp->der.value + 1) = (u8)oid->len; |
961 | 0 | memcpy(ecp->der.value + 2, oid->value, oid->len); |
962 | 0 | ecp->type = 1; // Named curve |
963 | |
|
964 | 0 | pubkey->alg_id = (struct sc_algorithm_id *)calloc(1, sizeof(struct sc_algorithm_id)); |
965 | 0 | if (!pubkey->alg_id) { |
966 | 0 | free(ecp->der.value); |
967 | 0 | free(ecp); |
968 | 0 | return SC_ERROR_OUT_OF_MEMORY; |
969 | 0 | } |
970 | | |
971 | 0 | pubkey->alg_id->algorithm = SC_ALGORITHM_EC; |
972 | 0 | pubkey->alg_id->params = ecp; |
973 | |
|
974 | 0 | pubkey->u.ec.ecpointQ.value = malloc(cvc->publicPointlen); |
975 | 0 | if (!pubkey->u.ec.ecpointQ.value) { |
976 | 0 | free(pubkey->alg_id); |
977 | 0 | free(ecp->der.value); |
978 | 0 | free(ecp); |
979 | 0 | return SC_ERROR_OUT_OF_MEMORY; |
980 | 0 | } |
981 | 0 | memcpy(pubkey->u.ec.ecpointQ.value, cvc->publicPoint, cvc->publicPointlen); |
982 | 0 | pubkey->u.ec.ecpointQ.len = cvc->publicPointlen; |
983 | |
|
984 | 0 | pubkey->u.ec.params.der.value = malloc(ecp->der.len); |
985 | 0 | if (!pubkey->u.ec.params.der.value) { |
986 | 0 | free(pubkey->u.ec.ecpointQ.value); |
987 | 0 | free(pubkey->alg_id); |
988 | 0 | free(ecp->der.value); |
989 | 0 | free(ecp); |
990 | 0 | return SC_ERROR_OUT_OF_MEMORY; |
991 | 0 | } |
992 | 0 | memcpy(pubkey->u.ec.params.der.value, ecp->der.value, ecp->der.len); |
993 | 0 | pubkey->u.ec.params.der.len = ecp->der.len; |
994 | | |
995 | | /* FIXME: check return value? */ |
996 | 0 | sc_pkcs15_fix_ec_parameters(ctx, &pubkey->u.ec.params); |
997 | |
|
998 | 0 | return SC_SUCCESS; |
999 | 0 | } |
1000 | | |
1001 | | |
1002 | | |
1003 | | int sc_pkcs15emu_sc_hsm_get_public_key(struct sc_context *ctx, sc_cvc_t *cvc, struct sc_pkcs15_pubkey *pubkey) |
1004 | 0 | { |
1005 | 0 | if (cvc->publicPoint && cvc->publicPointlen) { |
1006 | 0 | return sc_pkcs15emu_sc_hsm_get_ec_public_key(ctx, cvc, pubkey); |
1007 | 0 | } else { |
1008 | 0 | return sc_pkcs15emu_sc_hsm_get_rsa_public_key(ctx, cvc, pubkey); |
1009 | 0 | } |
1010 | 0 | } |
1011 | | |
1012 | | |
1013 | | |
1014 | | void sc_pkcs15emu_sc_hsm_free_cvc(sc_cvc_t *cvc) |
1015 | 6 | { |
1016 | 6 | if (cvc->outerSignature) { |
1017 | 0 | free(cvc->outerSignature); |
1018 | 0 | cvc->outerSignature = NULL; |
1019 | 0 | } |
1020 | 6 | if (cvc->signature) { |
1021 | 0 | free(cvc->signature); |
1022 | 0 | cvc->signature = NULL; |
1023 | 0 | } |
1024 | 6 | if (cvc->primeOrModulus) { |
1025 | 0 | free(cvc->primeOrModulus); |
1026 | 0 | cvc->primeOrModulus = NULL; |
1027 | 0 | } |
1028 | 6 | if (cvc->coefficientAorExponent) { |
1029 | 0 | free(cvc->coefficientAorExponent); |
1030 | 0 | cvc->coefficientAorExponent = NULL; |
1031 | 0 | } |
1032 | 6 | if (cvc->coefficientB) { |
1033 | 0 | free(cvc->coefficientB); |
1034 | 0 | cvc->coefficientB = NULL; |
1035 | 0 | } |
1036 | 6 | if (cvc->basePointG) { |
1037 | 0 | free(cvc->basePointG); |
1038 | 0 | cvc->basePointG = NULL; |
1039 | 0 | } |
1040 | 6 | if (cvc->order) { |
1041 | 0 | free(cvc->order); |
1042 | 0 | cvc->order = NULL; |
1043 | 0 | } |
1044 | 6 | if (cvc->publicPoint) { |
1045 | 0 | free(cvc->publicPoint); |
1046 | 0 | cvc->publicPoint = NULL; |
1047 | 0 | } |
1048 | 6 | if (cvc->cofactor) { |
1049 | 0 | free(cvc->cofactor); |
1050 | 0 | cvc->cofactor = NULL; |
1051 | 0 | } |
1052 | 6 | } |
1053 | | |
1054 | | void sc_pkcs15emu_sc_hsm_free_cvc_pka(sc_cvc_pka_t *pka) |
1055 | 0 | { |
1056 | 0 | sc_pkcs15emu_sc_hsm_free_cvc(&pka->public_key_req.cvc); |
1057 | 0 | sc_pkcs15emu_sc_hsm_free_cvc(&pka->device.cvc); |
1058 | 0 | sc_pkcs15emu_sc_hsm_free_cvc(&pka->dica.cvc); |
1059 | 0 | memset(pka, 0, sizeof(*pka)); |
1060 | 0 | } |
1061 | | |
1062 | | static int sc_pkcs15emu_sc_hsm_add_pubkey(sc_pkcs15_card_t *p15card, u8 *efbin, size_t len, sc_pkcs15_prkey_info_t *key_info, char *label) |
1063 | 0 | { |
1064 | 0 | struct sc_context *ctx = p15card->card->ctx; |
1065 | 0 | sc_card_t *card = p15card->card; |
1066 | 0 | sc_pkcs15_pubkey_info_t pubkey_info; |
1067 | 0 | sc_pkcs15_object_t pubkey_obj; |
1068 | 0 | struct sc_pkcs15_pubkey pubkey; |
1069 | 0 | sc_cvc_t cvc; |
1070 | 0 | u8 *cvcpo; |
1071 | 0 | int r; |
1072 | |
|
1073 | 0 | cvcpo = efbin; |
1074 | |
|
1075 | 0 | memset(&cvc, 0, sizeof(cvc)); |
1076 | 0 | r = sc_pkcs15emu_sc_hsm_decode_cvc(p15card, (const u8 **)&cvcpo, &len, &cvc); |
1077 | 0 | LOG_TEST_RET(ctx, r, "Could decode certificate signing request"); |
1078 | | |
1079 | 0 | memset(&pubkey, 0, sizeof(pubkey)); |
1080 | 0 | r = sc_pkcs15emu_sc_hsm_get_public_key(ctx, &cvc, &pubkey); |
1081 | 0 | LOG_TEST_RET(card->ctx, r, "Could not extract public key"); |
1082 | | |
1083 | 0 | memset(&pubkey_info, 0, sizeof(pubkey_info)); |
1084 | 0 | memset(&pubkey_obj, 0, sizeof(pubkey_obj)); |
1085 | |
|
1086 | 0 | r = sc_pkcs15_encode_pubkey(ctx, &pubkey, &pubkey_obj.content.value, &pubkey_obj.content.len); |
1087 | 0 | if (r != SC_SUCCESS) { |
1088 | 0 | sc_pkcs15_erase_pubkey(&pubkey); |
1089 | 0 | LOG_TEST_RET(ctx, r, "Could not encode public key"); |
1090 | 0 | } |
1091 | 0 | r = sc_pkcs15_encode_pubkey(ctx, &pubkey, &pubkey_info.direct.raw.value, &pubkey_info.direct.raw.len); |
1092 | 0 | if (r != SC_SUCCESS) { |
1093 | 0 | sc_pkcs15_erase_pubkey(&pubkey); |
1094 | 0 | LOG_TEST_RET(ctx, r, "Could not encode public key"); |
1095 | 0 | } |
1096 | 0 | r = sc_pkcs15_encode_pubkey_as_spki(ctx, &pubkey, &pubkey_info.direct.spki.value, &pubkey_info.direct.spki.len); |
1097 | 0 | if (r != SC_SUCCESS) { |
1098 | 0 | sc_pkcs15_erase_pubkey(&pubkey); |
1099 | 0 | LOG_TEST_RET(ctx, r, "Could not encode public key"); |
1100 | 0 | } |
1101 | | |
1102 | 0 | pubkey_info.id = key_info->id; |
1103 | 0 | strlcpy(pubkey_obj.label, label, sizeof(pubkey_obj.label)); |
1104 | |
|
1105 | 0 | if (pubkey.algorithm == SC_ALGORITHM_RSA) { |
1106 | 0 | pubkey_info.modulus_length = pubkey.u.rsa.modulus.len << 3; |
1107 | 0 | pubkey_info.usage = SC_PKCS15_PRKEY_USAGE_ENCRYPT|SC_PKCS15_PRKEY_USAGE_VERIFY|SC_PKCS15_PRKEY_USAGE_WRAP; |
1108 | 0 | r = sc_pkcs15emu_add_rsa_pubkey(p15card, &pubkey_obj, &pubkey_info); |
1109 | 0 | } else { |
1110 | | /* TODO fix if support of non multiple of 8 curves are added */ |
1111 | 0 | pubkey_info.field_length = cvc.primeOrModuluslen << 3; |
1112 | 0 | pubkey_info.usage = SC_PKCS15_PRKEY_USAGE_VERIFY|SC_PKCS15_PRKEY_USAGE_DERIVE; |
1113 | 0 | r = sc_pkcs15emu_add_ec_pubkey(p15card, &pubkey_obj, &pubkey_info); |
1114 | 0 | } |
1115 | 0 | if (r < 0) |
1116 | 0 | free(pubkey_info.direct.spki.value); |
1117 | 0 | LOG_TEST_RET(ctx, r, "Could not add public key"); |
1118 | | |
1119 | 0 | sc_pkcs15emu_sc_hsm_free_cvc(&cvc); |
1120 | 0 | sc_pkcs15_erase_pubkey(&pubkey); |
1121 | |
|
1122 | 0 | return SC_SUCCESS; |
1123 | 0 | } |
1124 | | |
1125 | | |
1126 | | |
1127 | | /* |
1128 | | * Add a key and the key description in PKCS#15 format to the framework |
1129 | | */ |
1130 | 0 | static int sc_pkcs15emu_sc_hsm_add_prkd(sc_pkcs15_card_t * p15card, u8 keyid) { |
1131 | |
|
1132 | 0 | sc_card_t *card = p15card->card; |
1133 | 0 | sc_pkcs15_cert_info_t cert_info; |
1134 | 0 | sc_pkcs15_object_t cert_obj; |
1135 | 0 | struct sc_pkcs15_object prkd; |
1136 | 0 | sc_pkcs15_prkey_info_t *key_info; |
1137 | 0 | u8 fid[2]; |
1138 | | /* enough to hold a complete certificate */ |
1139 | 0 | u8 efbin[4096]; |
1140 | 0 | u8 *ptr; |
1141 | 0 | size_t len; |
1142 | 0 | int r; |
1143 | |
|
1144 | 0 | if (keyid == 0) { |
1145 | | // Device authentication key does not have PKCS#15 meta data |
1146 | 0 | return SC_SUCCESS; |
1147 | 0 | } |
1148 | | |
1149 | 0 | fid[0] = PRKD_PREFIX; |
1150 | 0 | fid[1] = keyid; |
1151 | | |
1152 | | /* Try to select a related EF containing the PKCS#15 description of the key */ |
1153 | 0 | len = sizeof efbin; |
1154 | 0 | r = read_file(p15card, fid, efbin, &len, 1); |
1155 | 0 | LOG_TEST_RET(card->ctx, r, "Skipping optional EF.PRKD"); |
1156 | | |
1157 | 0 | ptr = efbin; |
1158 | |
|
1159 | 0 | memset(&prkd, 0, sizeof(prkd)); |
1160 | 0 | r = sc_pkcs15_decode_prkdf_entry(p15card, &prkd, (const u8 **)&ptr, &len); |
1161 | 0 | LOG_TEST_RET(card->ctx, r, "Skipping optional EF.PRKD"); |
1162 | | |
1163 | | /* All keys require user PIN authentication */ |
1164 | 0 | prkd.auth_id.len = 1; |
1165 | 0 | prkd.auth_id.value[0] = 1; |
1166 | | |
1167 | | /* |
1168 | | * Set private key flag as all keys are private anyway |
1169 | | */ |
1170 | 0 | prkd.flags |= SC_PKCS15_CO_FLAG_PRIVATE; |
1171 | |
|
1172 | 0 | key_info = (sc_pkcs15_prkey_info_t *)prkd.data; |
1173 | 0 | key_info->key_reference = keyid; |
1174 | 0 | key_info->path.aid.len = 0; |
1175 | |
|
1176 | 0 | if (prkd.type == SC_PKCS15_TYPE_PRKEY_RSA) { |
1177 | 0 | r = sc_pkcs15emu_add_rsa_prkey(p15card, &prkd, key_info); |
1178 | 0 | } else { |
1179 | 0 | if (key_info->field_length == 528) { |
1180 | | // Fix a bug for secp521 key generated with OpenSCDP |
1181 | 0 | key_info->field_length = 521; |
1182 | 0 | } |
1183 | 0 | r = sc_pkcs15emu_add_ec_prkey(p15card, &prkd, key_info); |
1184 | 0 | } |
1185 | |
|
1186 | 0 | LOG_TEST_RET(card->ctx, r, "Could not add private key to framework"); |
1187 | | |
1188 | | /* Check if we also have a certificate for the private key */ |
1189 | 0 | fid[0] = EE_CERTIFICATE_PREFIX; |
1190 | |
|
1191 | 0 | len = sizeof efbin; |
1192 | 0 | r = read_file(p15card, fid, efbin, &len, 0); |
1193 | 0 | LOG_TEST_RET(card->ctx, r, "Could not read EF"); |
1194 | | |
1195 | 0 | if (efbin[0] == 0x67) { /* Decode CSR and create public key object */ |
1196 | 0 | sc_pkcs15emu_sc_hsm_add_pubkey(p15card, efbin, len, key_info, prkd.label); |
1197 | 0 | free(key_info); |
1198 | 0 | return SC_SUCCESS; /* Ignore any errors */ |
1199 | 0 | } |
1200 | | |
1201 | 0 | if (efbin[0] != 0x30) { |
1202 | 0 | free(key_info); |
1203 | 0 | return SC_SUCCESS; |
1204 | 0 | } |
1205 | | |
1206 | 0 | memset(&cert_info, 0, sizeof(cert_info)); |
1207 | 0 | memset(&cert_obj, 0, sizeof(cert_obj)); |
1208 | |
|
1209 | 0 | cert_info.id = key_info->id; |
1210 | 0 | sc_path_set(&cert_info.path, SC_PATH_TYPE_FILE_ID, fid, 2, 0, 0); |
1211 | 0 | cert_info.path.count = -1; |
1212 | 0 | if (p15card->opts.use_file_cache) { |
1213 | | /* look this up with our AID, which should already be cached from the |
1214 | | * call to `read_file`. This may have the side effect that OpenSC's |
1215 | | * caching layer re-selects our applet *if the cached file cannot be |
1216 | | * found/used* and we may loose the authentication status. We assume |
1217 | | * that caching works perfectly without this side effect. */ |
1218 | 0 | cert_info.path.aid = sc_hsm_aid; |
1219 | 0 | } |
1220 | |
|
1221 | 0 | strlcpy(cert_obj.label, prkd.label, sizeof(cert_obj.label)); |
1222 | 0 | r = sc_pkcs15emu_add_x509_cert(p15card, &cert_obj, &cert_info); |
1223 | |
|
1224 | 0 | free(key_info); |
1225 | |
|
1226 | 0 | LOG_TEST_RET(card->ctx, r, "Could not add certificate"); |
1227 | | |
1228 | 0 | return SC_SUCCESS; |
1229 | 0 | } |
1230 | | |
1231 | | |
1232 | | |
1233 | | /* |
1234 | | * Add a data object and description in PKCS#15 format to the framework |
1235 | | */ |
1236 | 0 | static int sc_pkcs15emu_sc_hsm_add_dcod(sc_pkcs15_card_t * p15card, u8 id) { |
1237 | |
|
1238 | 0 | sc_card_t *card = p15card->card; |
1239 | 0 | sc_pkcs15_data_info_t *data_info; |
1240 | 0 | sc_pkcs15_object_t data_obj; |
1241 | 0 | u8 fid[2]; |
1242 | 0 | u8 efbin[512]; |
1243 | 0 | const u8 *ptr; |
1244 | 0 | size_t len; |
1245 | 0 | int r; |
1246 | |
|
1247 | 0 | fid[0] = DCOD_PREFIX; |
1248 | 0 | fid[1] = id; |
1249 | | |
1250 | | /* Try to select a related EF containing the PKCS#15 description of the data */ |
1251 | 0 | len = sizeof efbin; |
1252 | 0 | r = read_file(p15card, fid, efbin, &len, 1); |
1253 | 0 | LOG_TEST_RET(card->ctx, r, "Skipping optional EF.DCOD"); |
1254 | | |
1255 | 0 | ptr = efbin; |
1256 | |
|
1257 | 0 | memset(&data_obj, 0, sizeof(data_obj)); |
1258 | 0 | r = sc_pkcs15_decode_dodf_entry(p15card, &data_obj, &ptr, &len); |
1259 | 0 | LOG_TEST_RET(card->ctx, r, "Could not decode optional EF.DCOD"); |
1260 | | |
1261 | 0 | data_info = (sc_pkcs15_data_info_t *)data_obj.data; |
1262 | |
|
1263 | 0 | r = sc_pkcs15emu_add_data_object(p15card, &data_obj, data_info); |
1264 | |
|
1265 | 0 | LOG_TEST_RET(card->ctx, r, "Could not add data object to framework"); |
1266 | | |
1267 | 0 | return SC_SUCCESS; |
1268 | 0 | } |
1269 | | |
1270 | | |
1271 | | |
1272 | | /* |
1273 | | * Add a unrelated certificate object and description in PKCS#15 format to the framework |
1274 | | */ |
1275 | 0 | static int sc_pkcs15emu_sc_hsm_add_cd(sc_pkcs15_card_t * p15card, u8 id) { |
1276 | |
|
1277 | 0 | sc_card_t *card = p15card->card; |
1278 | 0 | sc_pkcs15_cert_info_t *cert_info; |
1279 | 0 | sc_pkcs15_object_t obj; |
1280 | 0 | u8 fid[2]; |
1281 | 0 | u8 efbin[512]; |
1282 | 0 | const u8 *ptr; |
1283 | 0 | size_t len; |
1284 | 0 | int r; |
1285 | |
|
1286 | 0 | fid[0] = CD_PREFIX; |
1287 | 0 | fid[1] = id; |
1288 | | |
1289 | | /* Try to select a related EF containing the PKCS#15 description of the data */ |
1290 | 0 | len = sizeof efbin; |
1291 | 0 | r = read_file(p15card, fid, efbin, &len, 1); |
1292 | 0 | LOG_TEST_RET(card->ctx, r, "Skipping optional EF.CDF"); |
1293 | | |
1294 | 0 | ptr = efbin; |
1295 | |
|
1296 | 0 | memset(&obj, 0, sizeof(obj)); |
1297 | 0 | r = sc_pkcs15_decode_cdf_entry(p15card, &obj, &ptr, &len); |
1298 | 0 | if (obj.data == NULL && r >= SC_SUCCESS) |
1299 | 0 | r = SC_ERROR_OBJECT_NOT_FOUND; |
1300 | 0 | LOG_TEST_RET(card->ctx, r, "Skipping optional EF.CDF"); |
1301 | | |
1302 | 0 | cert_info = (sc_pkcs15_cert_info_t *)obj.data; |
1303 | |
|
1304 | 0 | r = sc_pkcs15emu_add_x509_cert(p15card, &obj, cert_info); |
1305 | |
|
1306 | 0 | LOG_TEST_RET(card->ctx, r, "Could not add data object to framework"); |
1307 | | |
1308 | 0 | return SC_SUCCESS; |
1309 | 0 | } |
1310 | | |
1311 | | |
1312 | | |
1313 | | static int sc_pkcs15emu_sc_hsm_read_tokeninfo (sc_pkcs15_card_t * p15card) |
1314 | 0 | { |
1315 | 0 | sc_card_t *card = p15card->card; |
1316 | 0 | int r; |
1317 | 0 | u8 efbin[512]; |
1318 | 0 | size_t len; |
1319 | |
|
1320 | 0 | LOG_FUNC_CALLED(card->ctx); |
1321 | | |
1322 | | /* Read token info */ |
1323 | 0 | len = sizeof efbin; |
1324 | 0 | r = read_file(p15card, (u8 *) "\x2F\x03", efbin, &len, 1); |
1325 | 0 | LOG_TEST_RET(card->ctx, r, "Skipping optional EF.TokenInfo"); |
1326 | | |
1327 | 0 | r = sc_pkcs15_parse_tokeninfo(card->ctx, p15card->tokeninfo, efbin, len); |
1328 | 0 | LOG_TEST_RET(card->ctx, r, "Skipping optional EF.TokenInfo"); |
1329 | | |
1330 | 0 | LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); |
1331 | 0 | } |
1332 | | |
1333 | | |
1334 | | |
1335 | | /* |
1336 | | * Initialize PKCS#15 emulation with user PIN, private keys, certificate and data objects |
1337 | | * |
1338 | | */ |
1339 | | static int sc_pkcs15emu_sc_hsm_init (sc_pkcs15_card_t * p15card) |
1340 | 105 | { |
1341 | 105 | sc_card_t *card = p15card->card; |
1342 | 105 | sc_hsm_private_data_t *priv = (sc_hsm_private_data_t *) card->drv_data; |
1343 | 105 | sc_file_t *file = NULL; |
1344 | 105 | sc_path_t path; |
1345 | 105 | u8 filelist[MAX_EXT_APDU_LENGTH]; |
1346 | 105 | int filelistlength; |
1347 | 105 | int r, i; |
1348 | 105 | sc_cvc_t devcert; |
1349 | 105 | struct sc_app_info *appinfo; |
1350 | 105 | struct sc_pkcs15_auth_info pin_info; |
1351 | 105 | struct sc_pkcs15_object pin_obj; |
1352 | 105 | struct sc_pin_cmd_data pindata; |
1353 | 105 | u8 efbin[1024]; |
1354 | 105 | u8 *ptr; |
1355 | 105 | size_t len; |
1356 | | |
1357 | 105 | LOG_FUNC_CALLED(card->ctx); |
1358 | | |
1359 | 105 | appinfo = calloc(1, sizeof(struct sc_app_info)); |
1360 | | |
1361 | 105 | if (appinfo == NULL) { |
1362 | 0 | LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); |
1363 | 0 | } |
1364 | | |
1365 | 105 | appinfo->aid = sc_hsm_aid; |
1366 | | |
1367 | 105 | appinfo->ddo.aid = sc_hsm_aid; |
1368 | 105 | p15card->app = appinfo; |
1369 | | |
1370 | 105 | sc_path_set(&path, SC_PATH_TYPE_DF_NAME, sc_hsm_aid.value, sc_hsm_aid.len, 0, 0); |
1371 | 105 | r = sc_select_file(card, &path, &file); |
1372 | 105 | LOG_TEST_RET(card->ctx, r, "Could not select SmartCard-HSM application"); |
1373 | | |
1374 | 58 | p15card->card->version.hw_major = 24; /* JCOP 2.4.1r3 */ |
1375 | 58 | p15card->card->version.hw_minor = 13; |
1376 | 58 | if (file && file->prop_attr && file->prop_attr_len >= 2) { |
1377 | 4 | p15card->card->version.fw_major = file->prop_attr[file->prop_attr_len - 2]; |
1378 | 4 | p15card->card->version.fw_minor = file->prop_attr[file->prop_attr_len - 1]; |
1379 | 4 | } |
1380 | | |
1381 | 58 | sc_file_free(file); |
1382 | | |
1383 | | /* Read device certificate to determine serial number */ |
1384 | 58 | if (priv->EF_C_DevAut && priv->EF_C_DevAut_len) { |
1385 | 0 | ptr = priv->EF_C_DevAut; |
1386 | 0 | len = priv->EF_C_DevAut_len; |
1387 | 58 | } else { |
1388 | 58 | len = sizeof efbin; |
1389 | 58 | r = read_file(p15card, (u8 *) "\x2F\x02", efbin, &len, 1); |
1390 | 58 | LOG_TEST_RET(card->ctx, r, "Skipping optional EF.C_DevAut"); |
1391 | | |
1392 | 58 | if (len > 0) { |
1393 | | /* save EF_C_DevAut for further use */ |
1394 | 25 | ptr = realloc(priv->EF_C_DevAut, len); |
1395 | 25 | if (ptr) { |
1396 | 25 | memcpy(ptr, efbin, len); |
1397 | 25 | priv->EF_C_DevAut = ptr; |
1398 | 25 | priv->EF_C_DevAut_len = len; |
1399 | 25 | } |
1400 | 25 | } |
1401 | | |
1402 | 58 | ptr = efbin; |
1403 | 58 | } |
1404 | | |
1405 | 58 | memset(&devcert, 0 ,sizeof(devcert)); |
1406 | 58 | r = sc_pkcs15emu_sc_hsm_decode_cvc(p15card, (const u8 **)&ptr, &len, &devcert); |
1407 | 58 | LOG_TEST_RET(card->ctx, r, "Could not decode EF.C_DevAut"); |
1408 | | |
1409 | 0 | sc_pkcs15emu_sc_hsm_read_tokeninfo(p15card); |
1410 | |
|
1411 | 0 | if (p15card->tokeninfo->label == NULL) { |
1412 | 0 | if (p15card->card->type == SC_CARD_TYPE_SC_HSM_GOID |
1413 | 0 | || p15card->card->type == SC_CARD_TYPE_SC_HSM_SOC) { |
1414 | 0 | p15card->tokeninfo->label = strdup("GoID"); |
1415 | 0 | } else { |
1416 | 0 | p15card->tokeninfo->label = strdup("SmartCard-HSM"); |
1417 | 0 | } |
1418 | 0 | if (p15card->tokeninfo->label == NULL) |
1419 | 0 | LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); |
1420 | 0 | } |
1421 | | |
1422 | 0 | if ((p15card->tokeninfo->manufacturer_id != NULL) && !strcmp("(unknown)", p15card->tokeninfo->manufacturer_id)) { |
1423 | 0 | free(p15card->tokeninfo->manufacturer_id); |
1424 | 0 | p15card->tokeninfo->manufacturer_id = NULL; |
1425 | 0 | } |
1426 | |
|
1427 | 0 | if (p15card->tokeninfo->manufacturer_id == NULL) { |
1428 | 0 | if (p15card->card->type == SC_CARD_TYPE_SC_HSM_GOID |
1429 | 0 | || p15card->card->type == SC_CARD_TYPE_SC_HSM_SOC) { |
1430 | 0 | p15card->tokeninfo->manufacturer_id = strdup("Bundesdruckerei GmbH"); |
1431 | 0 | } else { |
1432 | 0 | p15card->tokeninfo->manufacturer_id = strdup("www.CardContact.de"); |
1433 | 0 | } |
1434 | 0 | if (p15card->tokeninfo->manufacturer_id == NULL) { |
1435 | 0 | sc_pkcs15_card_clear(p15card); |
1436 | 0 | LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); |
1437 | 0 | } |
1438 | 0 | } |
1439 | | |
1440 | 0 | appinfo->label = strdup(p15card->tokeninfo->label); |
1441 | 0 | if (appinfo->label == NULL) { |
1442 | 0 | sc_pkcs15_card_clear(p15card); |
1443 | 0 | LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); |
1444 | 0 | } |
1445 | | |
1446 | 0 | len = strnlen(devcert.chr, sizeof devcert.chr); /* Strip last 5 digit sequence number from CHR */ |
1447 | 0 | if (len < 8) |
1448 | 0 | return SC_ERROR_INTERNAL; |
1449 | 0 | len -= 5; |
1450 | |
|
1451 | 0 | free(p15card->tokeninfo->serial_number); |
1452 | 0 | p15card->tokeninfo->serial_number = calloc(1, len + 1); |
1453 | 0 | if (p15card->tokeninfo->serial_number == NULL) { |
1454 | 0 | sc_pkcs15_card_clear(p15card); |
1455 | 0 | LOG_FUNC_RETURN(card->ctx, SC_ERROR_OUT_OF_MEMORY); |
1456 | 0 | } |
1457 | | |
1458 | 0 | memcpy(p15card->tokeninfo->serial_number, devcert.chr, len); |
1459 | 0 | *(p15card->tokeninfo->serial_number + len) = 0; |
1460 | |
|
1461 | 0 | sc_hsm_set_serialnr(card, p15card->tokeninfo->serial_number); |
1462 | |
|
1463 | 0 | sc_pkcs15emu_sc_hsm_free_cvc(&devcert); |
1464 | |
|
1465 | 0 | memset(&pin_info, 0, sizeof(pin_info)); |
1466 | 0 | memset(&pin_obj, 0, sizeof(pin_obj)); |
1467 | |
|
1468 | 0 | pin_info.auth_id.len = 1; |
1469 | 0 | pin_info.auth_id.value[0] = 1; |
1470 | 0 | pin_info.path.aid = sc_hsm_aid; |
1471 | 0 | pin_info.auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN; |
1472 | 0 | pin_info.auth_method = SC_AC_CHV; |
1473 | 0 | pin_info.attrs.pin.reference = 0x81; |
1474 | 0 | pin_info.attrs.pin.flags = SC_PKCS15_PIN_FLAG_LOCAL|SC_PKCS15_PIN_FLAG_INITIALIZED|SC_PKCS15_PIN_FLAG_EXCHANGE_REF_DATA; |
1475 | 0 | pin_info.attrs.pin.type = SC_PKCS15_PIN_TYPE_ASCII_NUMERIC; |
1476 | 0 | pin_info.attrs.pin.min_length = 6; |
1477 | 0 | pin_info.attrs.pin.stored_length = 0; |
1478 | 0 | pin_info.attrs.pin.max_length = 15; |
1479 | 0 | pin_info.attrs.pin.pad_char = '\0'; |
1480 | 0 | pin_info.tries_left = 3; |
1481 | 0 | pin_info.max_tries = 3; |
1482 | |
|
1483 | 0 | pin_obj.auth_id.len = 1; |
1484 | 0 | pin_obj.auth_id.value[0] = 2; |
1485 | 0 | strlcpy(pin_obj.label, "UserPIN", sizeof(pin_obj.label)); |
1486 | 0 | pin_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE|SC_PKCS15_CO_FLAG_MODIFIABLE; |
1487 | |
|
1488 | 0 | pin_obj.data = &pin_info; |
1489 | |
|
1490 | 0 | r = sc_pkcs15_get_pin_info(p15card, &pin_obj); |
1491 | |
|
1492 | 0 | if (r != SC_ERROR_DATA_OBJECT_NOT_FOUND) { |
1493 | 0 | if (r < 0) { |
1494 | 0 | sc_pkcs15_card_clear(p15card); |
1495 | 0 | LOG_FUNC_RETURN(card->ctx, r); |
1496 | 0 | } |
1497 | | |
1498 | 0 | r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info); |
1499 | 0 | if (r < 0) { |
1500 | 0 | sc_pkcs15_card_clear(p15card); |
1501 | 0 | LOG_FUNC_RETURN(card->ctx, r); |
1502 | 0 | } |
1503 | 0 | } |
1504 | | |
1505 | 0 | memset(&pin_info, 0, sizeof(pin_info)); |
1506 | 0 | memset(&pin_obj, 0, sizeof(pin_obj)); |
1507 | |
|
1508 | 0 | pin_info.auth_id.len = 1; |
1509 | 0 | pin_info.auth_id.value[0] = 2; |
1510 | 0 | pin_info.path.aid = sc_hsm_aid; |
1511 | 0 | pin_info.auth_type = SC_PKCS15_PIN_AUTH_TYPE_PIN; |
1512 | 0 | pin_info.auth_method = SC_AC_CHV; |
1513 | 0 | pin_info.attrs.pin.reference = 0x88; |
1514 | 0 | pin_info.attrs.pin.flags = SC_PKCS15_PIN_FLAG_LOCAL|SC_PKCS15_PIN_FLAG_UNBLOCK_DISABLED|SC_PKCS15_PIN_FLAG_SO_PIN; |
1515 | 0 | pin_info.attrs.pin.type = SC_PKCS15_PIN_TYPE_BCD; |
1516 | 0 | pin_info.attrs.pin.min_length = 16; |
1517 | 0 | pin_info.attrs.pin.stored_length = 0; |
1518 | 0 | pin_info.attrs.pin.max_length = 16; |
1519 | 0 | pin_info.attrs.pin.pad_char = '\0'; |
1520 | 0 | pin_info.tries_left = 15; |
1521 | 0 | pin_info.max_tries = 15; |
1522 | |
|
1523 | 0 | strlcpy(pin_obj.label, "SOPIN", sizeof(pin_obj.label)); |
1524 | 0 | pin_obj.flags = SC_PKCS15_CO_FLAG_PRIVATE; |
1525 | |
|
1526 | 0 | pin_obj.data = &pin_info; |
1527 | |
|
1528 | 0 | r = sc_pkcs15_get_pin_info(p15card, &pin_obj); |
1529 | |
|
1530 | 0 | if (r != SC_ERROR_DATA_OBJECT_NOT_FOUND) { |
1531 | 0 | pin_info.attrs.pin.flags |= SC_PKCS15_PIN_FLAG_INITIALIZED; |
1532 | 0 | } else { |
1533 | 0 | r = SC_SUCCESS; |
1534 | 0 | } |
1535 | |
|
1536 | 0 | if (r < 0) { |
1537 | 0 | sc_pkcs15_card_clear(p15card); |
1538 | 0 | LOG_FUNC_RETURN(card->ctx, r); |
1539 | 0 | } |
1540 | | |
1541 | 0 | r = sc_pkcs15emu_add_pin_obj(p15card, &pin_obj, &pin_info); |
1542 | 0 | if (r < 0) { |
1543 | 0 | sc_pkcs15_card_clear(p15card); |
1544 | 0 | LOG_FUNC_RETURN(card->ctx, r); |
1545 | 0 | } |
1546 | | |
1547 | | |
1548 | 0 | if (card->type == SC_CARD_TYPE_SC_HSM_SOC |
1549 | 0 | || card->type == SC_CARD_TYPE_SC_HSM_GOID) { |
1550 | | /* SC-HSM of this type always has a PIN-Pad */ |
1551 | 0 | r = SC_SUCCESS; |
1552 | 0 | } else { |
1553 | 0 | memset(&pindata, 0, sizeof(pindata)); |
1554 | 0 | pindata.cmd = SC_PIN_CMD_GET_INFO; |
1555 | 0 | pindata.pin_type = SC_AC_CHV; |
1556 | 0 | pindata.pin_reference = 0x85; |
1557 | |
|
1558 | 0 | r = sc_pin_cmd(card, &pindata, NULL); |
1559 | 0 | } |
1560 | 0 | if (r == SC_ERROR_DATA_OBJECT_NOT_FOUND) { |
1561 | 0 | memset(&pindata, 0, sizeof(pindata)); |
1562 | 0 | pindata.cmd = SC_PIN_CMD_GET_INFO; |
1563 | 0 | pindata.pin_type = SC_AC_CHV; |
1564 | 0 | pindata.pin_reference = 0x86; |
1565 | |
|
1566 | 0 | r = sc_pin_cmd(card, &pindata, NULL); |
1567 | 0 | } |
1568 | |
|
1569 | 0 | if ((r != SC_ERROR_DATA_OBJECT_NOT_FOUND) && (r != SC_ERROR_INCORRECT_PARAMETERS) && (r != SC_ERROR_REF_DATA_NOT_USABLE)) |
1570 | 0 | card->caps |= SC_CARD_CAP_PROTECTED_AUTHENTICATION_PATH; |
1571 | | |
1572 | |
|
1573 | 0 | filelistlength = sc_list_files(card, filelist, sizeof(filelist)); |
1574 | 0 | if (filelistlength < 0) |
1575 | 0 | sc_pkcs15_card_clear(p15card); |
1576 | 0 | LOG_TEST_RET(card->ctx, filelistlength, "Could not enumerate file and key identifier"); |
1577 | | |
1578 | 0 | for (i = 0; i < filelistlength; i += 2) { |
1579 | 0 | switch(filelist[i]) { |
1580 | 0 | case KEY_PREFIX: |
1581 | 0 | r = sc_pkcs15emu_sc_hsm_add_prkd(p15card, filelist[i + 1]); |
1582 | 0 | break; |
1583 | 0 | case DCOD_PREFIX: |
1584 | 0 | r = sc_pkcs15emu_sc_hsm_add_dcod(p15card, filelist[i + 1]); |
1585 | 0 | break; |
1586 | 0 | case CD_PREFIX: |
1587 | 0 | r = sc_pkcs15emu_sc_hsm_add_cd(p15card, filelist[i + 1]); |
1588 | 0 | break; |
1589 | 0 | } |
1590 | 0 | if (r != SC_SUCCESS) { |
1591 | 0 | sc_log(card->ctx, "Error %d adding elements to framework", r); |
1592 | 0 | } |
1593 | 0 | } |
1594 | | |
1595 | 0 | LOG_FUNC_RETURN(card->ctx, SC_SUCCESS); |
1596 | 0 | } |
1597 | | |
1598 | | |
1599 | | |
1600 | | int sc_pkcs15emu_sc_hsm_init_ex(sc_pkcs15_card_t *p15card, |
1601 | | struct sc_aid *aid) |
1602 | 8.70k | { |
1603 | 8.70k | if (p15card->card->type != SC_CARD_TYPE_SC_HSM |
1604 | 8.70k | && p15card->card->type != SC_CARD_TYPE_SC_HSM_SOC |
1605 | 8.70k | && p15card->card->type != SC_CARD_TYPE_SC_HSM_GOID) { |
1606 | 8.59k | return SC_ERROR_WRONG_CARD; |
1607 | 8.59k | } |
1608 | 105 | return sc_pkcs15emu_sc_hsm_init(p15card); |
1609 | 8.70k | } |