blob: 45ea4afcc69c252976a7a503ab55e0de6fb009dc [file] [log] [blame]
Paul Bakker43b7e352011-01-18 15:27:19 +00001/**
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 *
Bence Szépkúti1e148272020-08-07 13:07:28 +02008 * Copyright The Mbed TLS Contributors
Dave Rodgman7ff79652023-11-03 12:04:52 +00009 * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
Paul Bakker43b7e352011-01-18 15:27:19 +000010 */
11
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000012#include "mbedtls/pkcs11.h"
Paul Bakker43b7e352011-01-18 15:27:19 +000013
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020014#if defined(MBEDTLS_PKCS11_C)
Rich Evans00ab4702015-02-06 13:43:58 +000015
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000016#include "mbedtls/md.h"
17#include "mbedtls/oid.h"
18#include "mbedtls/x509_crt.h"
Paul Bakker43b7e352011-01-18 15:27:19 +000019
Manuel Pégourié-Gonnard7f809972015-03-09 17:05:11 +000020#include "mbedtls/platform.h"
Paul Bakker6e339b52013-07-03 13:37:05 +020021
Manuel Pégourié-Gonnard3a895592015-05-27 17:09:21 +020022#include <string.h>
23
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010024void mbedtls_pkcs11_init(mbedtls_pkcs11_context *ctx)
Manuel Pégourié-Gonnardeab147c2015-04-29 01:10:10 +020025{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010026 memset(ctx, 0, sizeof(mbedtls_pkcs11_context));
Manuel Pégourié-Gonnardeab147c2015-04-29 01:10:10 +020027}
28
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010029int mbedtls_pkcs11_x509_cert_bind(mbedtls_x509_crt *cert, pkcs11h_certificate_t pkcs11_cert)
Paul Bakker43b7e352011-01-18 15:27:19 +000030{
31 int ret = 1;
32 unsigned char *cert_blob = NULL;
33 size_t cert_blob_size = 0;
34
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010035 if (cert == NULL) {
Paul Bakker43b7e352011-01-18 15:27:19 +000036 ret = 2;
37 goto cleanup;
38 }
39
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010040 if (pkcs11h_certificate_getCertificateBlob(pkcs11_cert, NULL,
41 &cert_blob_size) != CKR_OK) {
Paul Bakker43b7e352011-01-18 15:27:19 +000042 ret = 3;
43 goto cleanup;
44 }
45
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010046 cert_blob = mbedtls_calloc(1, cert_blob_size);
47 if (NULL == cert_blob) {
Paul Bakker43b7e352011-01-18 15:27:19 +000048 ret = 4;
49 goto cleanup;
50 }
51
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010052 if (pkcs11h_certificate_getCertificateBlob(pkcs11_cert, cert_blob,
53 &cert_blob_size) != CKR_OK) {
Paul Bakker43b7e352011-01-18 15:27:19 +000054 ret = 5;
55 goto cleanup;
56 }
57
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010058 if (0 != mbedtls_x509_crt_parse(cert, cert_blob, cert_blob_size)) {
Paul Bakker43b7e352011-01-18 15:27:19 +000059 ret = 6;
60 goto cleanup;
61 }
62
63 ret = 0;
64
65cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010066 if (NULL != cert_blob) {
67 mbedtls_free(cert_blob);
68 }
Paul Bakker43b7e352011-01-18 15:27:19 +000069
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010070 return ret;
Paul Bakker43b7e352011-01-18 15:27:19 +000071}
72
73
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010074int mbedtls_pkcs11_priv_key_bind(mbedtls_pkcs11_context *priv_key,
75 pkcs11h_certificate_t pkcs11_cert)
Paul Bakker43b7e352011-01-18 15:27:19 +000076{
77 int ret = 1;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +020078 mbedtls_x509_crt cert;
Paul Bakker43b7e352011-01-18 15:27:19 +000079
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010080 mbedtls_x509_crt_init(&cert);
Paul Bakker43b7e352011-01-18 15:27:19 +000081
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010082 if (priv_key == NULL) {
Paul Bakker43b7e352011-01-18 15:27:19 +000083 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010084 }
Paul Bakker43b7e352011-01-18 15:27:19 +000085
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010086 if (0 != mbedtls_pkcs11_x509_cert_bind(&cert, pkcs11_cert)) {
Paul Bakker43b7e352011-01-18 15:27:19 +000087 goto cleanup;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010088 }
Paul Bakker43b7e352011-01-18 15:27:19 +000089
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010090 priv_key->len = mbedtls_pk_get_len(&cert.pk);
Paul Bakker43b7e352011-01-18 15:27:19 +000091 priv_key->pkcs11h_cert = pkcs11_cert;
92
93 ret = 0;
94
95cleanup:
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010096 mbedtls_x509_crt_free(&cert);
Paul Bakker43b7e352011-01-18 15:27:19 +000097
Gilles Peskine1b6c09a2023-01-11 14:52:35 +010098 return ret;
Paul Bakker43b7e352011-01-18 15:27:19 +000099}
100
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100101void mbedtls_pkcs11_priv_key_free(mbedtls_pkcs11_context *priv_key)
Paul Bakker43b7e352011-01-18 15:27:19 +0000102{
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100103 if (NULL != priv_key) {
104 pkcs11h_certificate_freeCertificate(priv_key->pkcs11h_cert);
105 }
Paul Bakker43b7e352011-01-18 15:27:19 +0000106}
107
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100108int mbedtls_pkcs11_decrypt(mbedtls_pkcs11_context *ctx,
109 int mode, size_t *olen,
110 const unsigned char *input,
111 unsigned char *output,
112 size_t output_max_len)
Paul Bakker43b7e352011-01-18 15:27:19 +0000113{
114 size_t input_len, output_len;
115
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100116 if (NULL == ctx) {
117 return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
118 }
Paul Bakker43b7e352011-01-18 15:27:19 +0000119
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100120 if (MBEDTLS_RSA_PRIVATE != mode) {
121 return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
122 }
Paul Bakker43b7e352011-01-18 15:27:19 +0000123
124 output_len = input_len = ctx->len;
125
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100126 if (input_len < 16 || input_len > output_max_len) {
127 return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
128 }
Paul Bakker43b7e352011-01-18 15:27:19 +0000129
130 /* Determine size of output buffer */
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100131 if (pkcs11h_certificate_decryptAny(ctx->pkcs11h_cert, CKM_RSA_PKCS, input,
132 input_len, NULL, &output_len) != CKR_OK) {
133 return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
Paul Bakker43b7e352011-01-18 15:27:19 +0000134 }
135
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100136 if (output_len > output_max_len) {
137 return MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE;
138 }
Paul Bakker43b7e352011-01-18 15:27:19 +0000139
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100140 if (pkcs11h_certificate_decryptAny(ctx->pkcs11h_cert, CKM_RSA_PKCS, input,
141 input_len, output, &output_len) != CKR_OK) {
142 return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
Paul Bakker43b7e352011-01-18 15:27:19 +0000143 }
144 *olen = output_len;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100145 return 0;
Paul Bakker43b7e352011-01-18 15:27:19 +0000146}
147
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100148int mbedtls_pkcs11_sign(mbedtls_pkcs11_context *ctx,
149 int mode,
150 mbedtls_md_type_t md_alg,
151 unsigned int hashlen,
152 const unsigned char *hash,
153 unsigned char *sig)
Paul Bakker43b7e352011-01-18 15:27:19 +0000154{
Paul Bakkerdb1f0592014-03-26 14:53:47 +0100155 size_t sig_len = 0, asn_len = 0, oid_size = 0;
Paul Bakker43b7e352011-01-18 15:27:19 +0000156 unsigned char *p = sig;
Steffan Karger28d81a02013-11-13 16:57:58 +0100157 const char *oid;
Paul Bakker43b7e352011-01-18 15:27:19 +0000158
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100159 if (NULL == ctx) {
160 return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
161 }
Paul Bakker43b7e352011-01-18 15:27:19 +0000162
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100163 if (MBEDTLS_RSA_PRIVATE != mode) {
164 return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
165 }
Paul Bakker43b7e352011-01-18 15:27:19 +0000166
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100167 if (md_alg != MBEDTLS_MD_NONE) {
168 const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type(md_alg);
169 if (md_info == NULL) {
170 return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
171 }
Steffan Karger28d81a02013-11-13 16:57:58 +0100172
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100173 if (mbedtls_oid_get_oid_by_md(md_alg, &oid, &oid_size) != 0) {
174 return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
175 }
Steffan Karger28d81a02013-11-13 16:57:58 +0100176
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100177 hashlen = mbedtls_md_get_size(md_info);
Paul Bakkerdb1f0592014-03-26 14:53:47 +0100178 asn_len = 10 + oid_size;
Steffan Karger28d81a02013-11-13 16:57:58 +0100179 }
180
Paul Bakkerdb1f0592014-03-26 14:53:47 +0100181 sig_len = ctx->len;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100182 if (hashlen > sig_len || asn_len > sig_len ||
183 hashlen + asn_len > sig_len) {
184 return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
Steffan Karger28d81a02013-11-13 16:57:58 +0100185 }
Paul Bakkerdb1f0592014-03-26 14:53:47 +0100186
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100187 if (md_alg != MBEDTLS_MD_NONE) {
Steffan Karger28d81a02013-11-13 16:57:58 +0100188 /*
189 * DigestInfo ::= SEQUENCE {
190 * digestAlgorithm DigestAlgorithmIdentifier,
191 * digest Digest }
192 *
193 * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
194 *
195 * Digest ::= OCTET STRING
196 */
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200197 *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100198 *p++ = (unsigned char) (0x08 + oid_size + hashlen);
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200199 *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100200 *p++ = (unsigned char) (0x04 + oid_size);
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200201 *p++ = MBEDTLS_ASN1_OID;
Steffan Karger28d81a02013-11-13 16:57:58 +0100202 *p++ = oid_size & 0xFF;
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100203 memcpy(p, oid, oid_size);
Steffan Karger28d81a02013-11-13 16:57:58 +0100204 p += oid_size;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200205 *p++ = MBEDTLS_ASN1_NULL;
Steffan Karger28d81a02013-11-13 16:57:58 +0100206 *p++ = 0x00;
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200207 *p++ = MBEDTLS_ASN1_OCTET_STRING;
Steffan Karger28d81a02013-11-13 16:57:58 +0100208 *p++ = hashlen;
Paul Bakker43b7e352011-01-18 15:27:19 +0000209 }
210
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100211 memcpy(p, hash, hashlen);
Paul Bakkerdb1f0592014-03-26 14:53:47 +0100212
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100213 if (pkcs11h_certificate_signAny(ctx->pkcs11h_cert, CKM_RSA_PKCS, sig,
214 asn_len + hashlen, sig, &sig_len) != CKR_OK) {
215 return MBEDTLS_ERR_RSA_BAD_INPUT_DATA;
Paul Bakker43b7e352011-01-18 15:27:19 +0000216 }
217
Gilles Peskine1b6c09a2023-01-11 14:52:35 +0100218 return 0;
Paul Bakker43b7e352011-01-18 15:27:19 +0000219}
220
Manuel Pégourié-Gonnard2cf5a7c2015-04-08 12:49:31 +0200221#endif /* defined(MBEDTLS_PKCS11_C) */