1 | /** |
2 | * \file pkcs11.c |
3 | * |
4 | * \brief Wrapper for PKCS#11 library libpkcs11-helper |
5 | * |
6 | * \author Adriaan de Jong <dejong@fox-it.com> |
7 | * |
8 | * Copyright The Mbed TLS Contributors |
9 | * SPDX-License-Identifier: Apache-2.0 |
10 | * |
11 | * Licensed under the Apache License, Version 2.0 (the "License"); you may |
12 | * not use this file except in compliance with the License. |
13 | * You may obtain a copy of the License at |
14 | * |
15 | * http://www.apache.org/licenses/LICENSE-2.0 |
16 | * |
17 | * Unless required by applicable law or agreed to in writing, software |
18 | * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT |
19 | * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
20 | * See the License for the specific language governing permissions and |
21 | * limitations under the License. |
22 | */ |
23 | |
24 | #include "mbedtls/pkcs11.h" |
25 | |
26 | #if defined(MBEDTLS_PKCS11_C) |
27 | |
28 | #include "mbedtls/md.h" |
29 | #include "mbedtls/oid.h" |
30 | #include "mbedtls/x509_crt.h" |
31 | |
32 | #include "mbedtls/platform.h" |
33 | |
34 | #include <string.h> |
35 | |
36 | void mbedtls_pkcs11_init(mbedtls_pkcs11_context *ctx) |
37 | { |
38 | memset(ctx, 0, sizeof(mbedtls_pkcs11_context)); |
39 | } |
40 | |
41 | int mbedtls_pkcs11_x509_cert_bind(mbedtls_x509_crt *cert, pkcs11h_certificate_t pkcs11_cert) |
42 | { |
43 | int ret = 1; |
44 | unsigned char *cert_blob = NULL; |
45 | size_t cert_blob_size = 0; |
46 | |
47 | if (cert == NULL) { |
48 | ret = 2; |
49 | goto cleanup; |
50 | } |
51 | |
52 | if (pkcs11h_certificate_getCertificateBlob(pkcs11_cert, NULL, |
53 | &cert_blob_size) != CKR_OK) { |
54 | ret = 3; |
55 | goto cleanup; |
56 | } |
57 | |
58 | cert_blob = mbedtls_calloc(1, cert_blob_size); |
59 | if (NULL == cert_blob) { |
60 | ret = 4; |
61 | goto cleanup; |
62 | } |
63 | |
64 | if (pkcs11h_certificate_getCertificateBlob(pkcs11_cert, cert_blob, |
65 | &cert_blob_size) != CKR_OK) { |
66 | ret = 5; |
67 | goto cleanup; |
68 | } |
69 | |
70 | if (0 != mbedtls_x509_crt_parse(cert, cert_blob, cert_blob_size)) { |
71 | ret = 6; |
72 | goto cleanup; |
73 | } |
74 | |
75 | ret = 0; |
76 | |
77 | cleanup: |
78 | if (NULL != cert_blob) { |
79 | mbedtls_free(cert_blob); |
80 | } |
81 | |
82 | return ret; |
83 | } |
84 | |
85 | |
86 | int mbedtls_pkcs11_priv_key_bind(mbedtls_pkcs11_context *priv_key, |
87 | pkcs11h_certificate_t pkcs11_cert) |
88 | { |
89 | int ret = 1; |
90 | mbedtls_x509_crt cert; |
91 | |
92 | mbedtls_x509_crt_init(&cert); |
93 | |
94 | if (priv_key == NULL) { |
95 | goto cleanup; |
96 | } |
97 | |
98 | if (0 != mbedtls_pkcs11_x509_cert_bind(&cert, pkcs11_cert)) { |
99 | goto cleanup; |
100 | } |
101 | |
102 | priv_key->len = mbedtls_pk_get_len(&cert.pk); |
103 | priv_key->pkcs11h_cert = pkcs11_cert; |
104 | |
105 | ret = 0; |
106 | |
107 | cleanup: |
108 | mbedtls_x509_crt_free(&cert); |
109 | |
110 | return ret; |
111 | } |
112 | |
113 | void mbedtls_pkcs11_priv_key_free(mbedtls_pkcs11_context *priv_key) |
114 | { |
115 | if (NULL != priv_key) { |
116 | pkcs11h_certificate_freeCertificate(priv_key->pkcs11h_cert); |
117 | } |
118 | } |
119 | |
120 | int mbedtls_pkcs11_decrypt(mbedtls_pkcs11_context *ctx, |
121 | int mode, size_t *olen, |
122 | const unsigned char *input, |
123 | unsigned char *output, |
124 | size_t output_max_len) |
125 | { |
126 | size_t input_len, output_len; |
127 | |
128 | if (NULL == ctx) { |
129 | return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; |
130 | } |
131 | |
132 | if (MBEDTLS_RSA_PRIVATE != mode) { |
133 | return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; |
134 | } |
135 | |
136 | output_len = input_len = ctx->len; |
137 | |
138 | if (input_len < 16 || input_len > output_max_len) { |
139 | return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; |
140 | } |
141 | |
142 | /* Determine size of output buffer */ |
143 | if (pkcs11h_certificate_decryptAny(ctx->pkcs11h_cert, CKM_RSA_PKCS, input, |
144 | input_len, NULL, &output_len) != CKR_OK) { |
145 | return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; |
146 | } |
147 | |
148 | if (output_len > output_max_len) { |
149 | return MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE; |
150 | } |
151 | |
152 | if (pkcs11h_certificate_decryptAny(ctx->pkcs11h_cert, CKM_RSA_PKCS, input, |
153 | input_len, output, &output_len) != CKR_OK) { |
154 | return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; |
155 | } |
156 | *olen = output_len; |
157 | return 0; |
158 | } |
159 | |
160 | int mbedtls_pkcs11_sign(mbedtls_pkcs11_context *ctx, |
161 | int mode, |
162 | mbedtls_md_type_t md_alg, |
163 | unsigned int hashlen, |
164 | const unsigned char *hash, |
165 | unsigned char *sig) |
166 | { |
167 | size_t sig_len = 0, asn_len = 0, oid_size = 0; |
168 | unsigned char *p = sig; |
169 | const char *oid; |
170 | |
171 | if (NULL == ctx) { |
172 | return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; |
173 | } |
174 | |
175 | if (MBEDTLS_RSA_PRIVATE != mode) { |
176 | return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; |
177 | } |
178 | |
179 | if (md_alg != MBEDTLS_MD_NONE) { |
180 | const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md_alg); |
181 | if (md_info == NULL) { |
182 | return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; |
183 | } |
184 | |
185 | if (mbedtls_oid_get_oid_by_md(md_alg, &oid, &oid_size) != 0) { |
186 | return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; |
187 | } |
188 | |
189 | hashlen = mbedtls_md_get_size(md_info); |
190 | asn_len = 10 + oid_size; |
191 | } |
192 | |
193 | sig_len = ctx->len; |
194 | if (hashlen > sig_len || asn_len > sig_len || |
195 | hashlen + asn_len > sig_len) { |
196 | return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; |
197 | } |
198 | |
199 | if (md_alg != MBEDTLS_MD_NONE) { |
200 | /* |
201 | * DigestInfo ::= SEQUENCE { |
202 | * digestAlgorithm DigestAlgorithmIdentifier, |
203 | * digest Digest } |
204 | * |
205 | * DigestAlgorithmIdentifier ::= AlgorithmIdentifier |
206 | * |
207 | * Digest ::= OCTET STRING |
208 | */ |
209 | *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; |
210 | *p++ = (unsigned char) (0x08 + oid_size + hashlen); |
211 | *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; |
212 | *p++ = (unsigned char) (0x04 + oid_size); |
213 | *p++ = MBEDTLS_ASN1_OID; |
214 | *p++ = oid_size & 0xFF; |
215 | memcpy(p, oid, oid_size); |
216 | p += oid_size; |
217 | *p++ = MBEDTLS_ASN1_NULL; |
218 | *p++ = 0x00; |
219 | *p++ = MBEDTLS_ASN1_OCTET_STRING; |
220 | *p++ = hashlen; |
221 | } |
222 | |
223 | memcpy(p, hash, hashlen); |
224 | |
225 | if (pkcs11h_certificate_signAny(ctx->pkcs11h_cert, CKM_RSA_PKCS, sig, |
226 | asn_len + hashlen, sig, &sig_len) != CKR_OK) { |
227 | return MBEDTLS_ERR_RSA_BAD_INPUT_DATA; |
228 | } |
229 | |
230 | return 0; |
231 | } |
232 | |
233 | #endif /* defined(MBEDTLS_PKCS11_C) */ |
234 | |