xref: /reactos/dll/3rdparty/mbedtls/pkcs11.c (revision 5100859e)
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 (C) 2006-2015, ARM Limited, All Rights Reserved
9  *  SPDX-License-Identifier: GPL-2.0
10  *
11  *  This program is free software; you can redistribute it and/or modify
12  *  it under the terms of the GNU General Public License as published by
13  *  the Free Software Foundation; either version 2 of the License, or
14  *  (at your option) any later version.
15  *
16  *  This program is distributed in the hope that it will be useful,
17  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
18  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  *  GNU General Public License for more details.
20  *
21  *  You should have received a copy of the GNU General Public License along
22  *  with this program; if not, write to the Free Software Foundation, Inc.,
23  *  51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24  *
25  *  This file is part of mbed TLS (https://tls.mbed.org)
26  */
27 
28 #include "mbedtls/pkcs11.h"
29 
30 #if defined(MBEDTLS_PKCS11_C)
31 
32 #include "mbedtls/md.h"
33 #include "mbedtls/oid.h"
34 #include "mbedtls/x509_crt.h"
35 
36 #if defined(MBEDTLS_PLATFORM_C)
37 #include "mbedtls/platform.h"
38 #else
39 #include <stdlib.h>
40 #define mbedtls_calloc    calloc
41 #define mbedtls_free       free
42 #endif
43 
44 #include <string.h>
45 
46 void mbedtls_pkcs11_init( mbedtls_pkcs11_context *ctx )
47 {
48     memset( ctx, 0, sizeof( mbedtls_pkcs11_context ) );
49 }
50 
51 int mbedtls_pkcs11_x509_cert_bind( mbedtls_x509_crt *cert, pkcs11h_certificate_t pkcs11_cert )
52 {
53     int ret = 1;
54     unsigned char *cert_blob = NULL;
55     size_t cert_blob_size = 0;
56 
57     if( cert == NULL )
58     {
59         ret = 2;
60         goto cleanup;
61     }
62 
63     if( pkcs11h_certificate_getCertificateBlob( pkcs11_cert, NULL,
64                                                 &cert_blob_size ) != CKR_OK )
65     {
66         ret = 3;
67         goto cleanup;
68     }
69 
70     cert_blob = mbedtls_calloc( 1, cert_blob_size );
71     if( NULL == cert_blob )
72     {
73         ret = 4;
74         goto cleanup;
75     }
76 
77     if( pkcs11h_certificate_getCertificateBlob( pkcs11_cert, cert_blob,
78                                                 &cert_blob_size ) != CKR_OK )
79     {
80         ret = 5;
81         goto cleanup;
82     }
83 
84     if( 0 != mbedtls_x509_crt_parse( cert, cert_blob, cert_blob_size ) )
85     {
86         ret = 6;
87         goto cleanup;
88     }
89 
90     ret = 0;
91 
92 cleanup:
93     if( NULL != cert_blob )
94         mbedtls_free( cert_blob );
95 
96     return( ret );
97 }
98 
99 
100 int mbedtls_pkcs11_priv_key_bind( mbedtls_pkcs11_context *priv_key,
101         pkcs11h_certificate_t pkcs11_cert )
102 {
103     int ret = 1;
104     mbedtls_x509_crt cert;
105 
106     mbedtls_x509_crt_init( &cert );
107 
108     if( priv_key == NULL )
109         goto cleanup;
110 
111     if( 0 != mbedtls_pkcs11_x509_cert_bind( &cert, pkcs11_cert ) )
112         goto cleanup;
113 
114     priv_key->len = mbedtls_pk_get_len( &cert.pk );
115     priv_key->pkcs11h_cert = pkcs11_cert;
116 
117     ret = 0;
118 
119 cleanup:
120     mbedtls_x509_crt_free( &cert );
121 
122     return( ret );
123 }
124 
125 void mbedtls_pkcs11_priv_key_free( mbedtls_pkcs11_context *priv_key )
126 {
127     if( NULL != priv_key )
128         pkcs11h_certificate_freeCertificate( priv_key->pkcs11h_cert );
129 }
130 
131 int mbedtls_pkcs11_decrypt( mbedtls_pkcs11_context *ctx,
132                        int mode, size_t *olen,
133                        const unsigned char *input,
134                        unsigned char *output,
135                        size_t output_max_len )
136 {
137     size_t input_len, output_len;
138 
139     if( NULL == ctx )
140         return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
141 
142     if( MBEDTLS_RSA_PRIVATE != mode )
143         return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
144 
145     output_len = input_len = ctx->len;
146 
147     if( input_len < 16 || input_len > output_max_len )
148         return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
149 
150     /* Determine size of output buffer */
151     if( pkcs11h_certificate_decryptAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, input,
152             input_len, NULL, &output_len ) != CKR_OK )
153     {
154         return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
155     }
156 
157     if( output_len > output_max_len )
158         return( MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE );
159 
160     if( pkcs11h_certificate_decryptAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, input,
161             input_len, output, &output_len ) != CKR_OK )
162     {
163         return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
164     }
165     *olen = output_len;
166     return( 0 );
167 }
168 
169 int mbedtls_pkcs11_sign( mbedtls_pkcs11_context *ctx,
170                     int mode,
171                     mbedtls_md_type_t md_alg,
172                     unsigned int hashlen,
173                     const unsigned char *hash,
174                     unsigned char *sig )
175 {
176     size_t sig_len = 0, asn_len = 0, oid_size = 0;
177     unsigned char *p = sig;
178     const char *oid;
179 
180     if( NULL == ctx )
181         return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
182 
183     if( MBEDTLS_RSA_PRIVATE != mode )
184         return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
185 
186     if( md_alg != MBEDTLS_MD_NONE )
187     {
188         const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg );
189         if( md_info == NULL )
190             return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
191 
192         if( mbedtls_oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 )
193             return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
194 
195         hashlen = mbedtls_md_get_size( md_info );
196         asn_len = 10 + oid_size;
197     }
198 
199     sig_len = ctx->len;
200     if( hashlen > sig_len || asn_len > sig_len ||
201         hashlen + asn_len > sig_len )
202     {
203         return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
204     }
205 
206     if( md_alg != MBEDTLS_MD_NONE )
207     {
208         /*
209          * DigestInfo ::= SEQUENCE {
210          *   digestAlgorithm DigestAlgorithmIdentifier,
211          *   digest Digest }
212          *
213          * DigestAlgorithmIdentifier ::= AlgorithmIdentifier
214          *
215          * Digest ::= OCTET STRING
216          */
217         *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED;
218         *p++ = (unsigned char) ( 0x08 + oid_size + hashlen );
219         *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED;
220         *p++ = (unsigned char) ( 0x04 + oid_size );
221         *p++ = MBEDTLS_ASN1_OID;
222         *p++ = oid_size & 0xFF;
223         memcpy( p, oid, oid_size );
224         p += oid_size;
225         *p++ = MBEDTLS_ASN1_NULL;
226         *p++ = 0x00;
227         *p++ = MBEDTLS_ASN1_OCTET_STRING;
228         *p++ = hashlen;
229     }
230 
231     memcpy( p, hash, hashlen );
232 
233     if( pkcs11h_certificate_signAny( ctx->pkcs11h_cert, CKM_RSA_PKCS, sig,
234             asn_len + hashlen, sig, &sig_len ) != CKR_OK )
235     {
236         return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA );
237     }
238 
239     return( 0 );
240 }
241 
242 #endif /* defined(MBEDTLS_PKCS11_C) */
243