blob: 1dfe70d981da111d3b50b15cdf479c227bb75eef [file] [log] [blame]
Andrzej Kurekc53dee32018-01-23 05:44:20 -05001/* BEGIN_HEADER */
2#include <string.h>
3
4#include <pkcs11.h>
5
6#include "mbedtls/pkcs11_client.h"
7
8#if defined(MBEDTLS_PK_C)
9
10#include "mbedtls/oid.h"
11#include "mbedtls/asn1write.h"
12#include "mbedtls/bignum.h"
13#include "mbedtls/rsa.h"
14#include "mbedtls/pk.h"
15
16#define ARRAY_LENGTH( a ) ( sizeof( a ) / sizeof( *( a ) ) )
17
18#define CK_ASSERT( expr ) \
19 do { \
20 CK_RV CK_ASSERT_rv = ( expr ); \
21 char CK_ASSERT_msg[sizeof( #expr ) + 20] = #expr; \
22 if( CK_ASSERT_rv != CKR_OK ) { \
23 sprintf( CK_ASSERT_msg + strlen( CK_ASSERT_msg ), \
24 " -> 0x%x", (unsigned) CK_ASSERT_rv ); \
25 test_fail( CK_ASSERT_msg, __LINE__, __FILE__ ); \
26 goto exit; \
27 } \
28 } while( 0 )
29
30#define RSA_KEY_SIZE_BITS 512
31#define RSA_KEY_SIZE_BYTES ( ( RSA_KEY_SIZE_BITS + 7 ) / 8 )
32#define ECP_GROUP_ID MBEDTLS_ECP_DP_SECP256R1
33#define ECP_GROUP_NAME( id ) #id
34
35//static CK_BBOOL ck_false = CK_FALSE;
36static CK_BBOOL ck_true = CK_TRUE;
37
38static int pkcs11_token_label_is( const CK_TOKEN_INFO *info, const char *label )
39{
40 size_t n = strlen( label );
41 if( n > sizeof( info->label ) )
42 return( 0 );
43 if( memcmp( info->label, label, n ) )
44 return( 0 );
45 for( ; n < sizeof( info->label ); n++ )
46 {
47 if( info->label[n] != ' ' )
48 return( 0 );
49 }
50 return( 1 );
51}
52
53static int pkcs11_get_slot_id( const char *label, CK_SLOT_ID *slot )
54{
55 CK_SLOT_ID *slots = NULL;
56 CK_ULONG count;
57 CK_ULONG i;
58 CK_TOKEN_INFO info;
59 int found = 0;
60 CK_ASSERT( C_GetSlotList( CK_TRUE, NULL_PTR, &count ) );
61 slots = mbedtls_calloc( sizeof( *slots ), count );
62 TEST_ASSERT( slots != NULL );
63 CK_ASSERT( C_GetSlotList( CK_TRUE, slots, &count ) );
64 for( i = 0; i < count; i++ )
65 {
66 CK_ASSERT( C_GetTokenInfo( slots[i], &info ) );
67 if( pkcs11_token_label_is( &info, label ) )
68 {
69 *slot = slots[i];
70 found = 1;
71 break;
72 }
73 }
74 if( !found )
75 mbedtls_fprintf( stdout, "No token found with label %s\n", label );
76exit:
77 mbedtls_free( slots );
78 return( found );
79}
80
81static CK_OBJECT_HANDLE pkcs11_init( void )
82{
83 CK_SESSION_HANDLE hSession;
84 CK_SLOT_ID slot;
85 unsigned char user_pin[4] = "0000";
86 CK_ASSERT( C_Initialize( NULL_PTR ) );
87 TEST_ASSERT( pkcs11_get_slot_id( "scratch", &slot ) );
88 CK_ASSERT( C_OpenSession( slot,
89 CKF_RW_SESSION | CKF_SERIAL_SESSION,
90 NULL_PTR, NULL_PTR,
91 &hSession ) );
92 CK_ASSERT( C_Login( hSession, CKU_USER, user_pin, sizeof( user_pin ) ) );
93 return( hSession );
94exit:
95 return( CK_INVALID_HANDLE );
96}
97
98static CK_RV pkcs11_generate_key( mbedtls_pk_type_t key_type,
99 CK_SESSION_HANDLE hSession,
100 CK_OBJECT_HANDLE *phPublicKey,
101 CK_OBJECT_HANDLE *phPrivateKey )
102{
103 CK_MECHANISM mechanism = {0, NULL_PTR, 0};
104 CK_ATTRIBUTE public_attributes[] = {
105 {0, 0, 0},
106 {CKA_ENCRYPT, &ck_true, sizeof( ck_true )},
107 {CKA_VERIFY, &ck_true, sizeof( ck_true )},
108 };
109 CK_ATTRIBUTE private_attributes[] = {
110 {CKA_DECRYPT, &ck_true, sizeof( ck_true )},
111 {CKA_SIGN, &ck_true, sizeof( ck_true )},
112 };
113 CK_ULONG ck_rsa_key_size = RSA_KEY_SIZE_BITS;
114 unsigned char ecParams[16];
115 size_t ecParams_length;
116
117 switch( key_type )
118 {
119#if defined(MBEDTLS_ECDSA_C)
120 case MBEDTLS_PK_ECDSA:
121 {
122 const char *oid;
123 size_t oid_length;
124 unsigned char *p;
125 TEST_ASSERT( mbedtls_oid_get_oid_by_ec_grp( ECP_GROUP_ID,
126 &oid, &oid_length ) == 0 );
127 ecParams_length = 2 + oid_length;
128 p = ecParams + ecParams_length;
129 TEST_ASSERT( mbedtls_asn1_write_oid( &p, ecParams, oid, oid_length ) > 0 );
130 }
131 mechanism.mechanism = CKM_EC_KEY_PAIR_GEN;
132 public_attributes[0].type = CKA_EC_PARAMS;
133 public_attributes[0].pValue = ecParams;
134 public_attributes[0].ulValueLen = ecParams_length;
135 break;
136#endif /* MBEDTLS_ECDSA_C */
137 default:
138 test_fail( "Unsupported key type in test data", __LINE__, __FILE__ );
139 break;
140 }
141
142 return( C_GenerateKeyPair( hSession,
143 &mechanism,
144 public_attributes,
145 ARRAY_LENGTH( public_attributes ),
146 private_attributes,
147 ARRAY_LENGTH( private_attributes ),
148 phPublicKey, phPrivateKey ) );
149exit:
150 /* Shouldn't happen except if there's a test error (e.g. trying to
151 use a curve that isn't compiled in). */
152 return( -1 );
153}
154
155
156#endif /* MBEDTLS_PK_C */
157
158/* END_HEADER */
159
160/* BEGIN_DEPENDENCIES
161 * depends_on:MBEDTLS_PKCS11_CLIENT_C
162 * END_DEPENDENCIES
163 */
164
165/* BEGIN_CASE depends_on:MBEDTLS_PK_C:MBEDTLS_SHA256_C */
166void pk_generate_sign( int key_type )
167{
168 mbedtls_pk_context pkcs11_ctx;
169 mbedtls_pk_context transparent_ctx;
170 CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
171 CK_OBJECT_HANDLE hPublicKey = CK_INVALID_HANDLE;
172 CK_OBJECT_HANDLE hPrivateKey = CK_INVALID_HANDLE;
173 unsigned char hash_value[32] = "Fake hash, it doesn't matter....";
174 unsigned char sig_buffer[RSA_KEY_SIZE_BYTES];
175 size_t sig_length = sizeof( sig_buffer );
176
177 mbedtls_pk_init( &pkcs11_ctx );
178 mbedtls_pk_init( &transparent_ctx );
179
180 /* Initialize cryptoki and generate a key in the token */
181 hSession = pkcs11_init( );
182 TEST_ASSERT( hSession != CK_INVALID_HANDLE );
183
184 CK_ASSERT( pkcs11_generate_key( key_type,
185 hSession,
186 &hPublicKey, &hPrivateKey ) );
187 TEST_ASSERT( hPublicKey != CK_INVALID_HANDLE );
188 TEST_ASSERT( hPrivateKey != CK_INVALID_HANDLE );
189
190 /* Prepare the mbed TLS contexts */
191 TEST_ASSERT( mbedtls_pk_setup( &transparent_ctx,
192 mbedtls_pk_info_from_type( key_type ) ) == 0 );
193 TEST_ASSERT( mbedtls_pk_setup_pkcs11( &pkcs11_ctx,
194 hSession,
195 hPublicKey,
196 hPrivateKey ) == 0 );
197
198 /* Retrieve the public key from the token */
199 switch( key_type )
200 {
201#if defined(MBEDTLS_ECDSA_C)
202 case MBEDTLS_PK_ECDSA:
203 {
204 unsigned char ecParams[16];
205 unsigned char ecPoint[128];
206 CK_ATTRIBUTE public_attributes[] = {
207 {CKA_EC_PARAMS, ecParams, sizeof( ecParams )},
208 {CKA_EC_POINT, ecPoint, sizeof( ecPoint )},
209 };
210 mbedtls_ecp_keypair *ecp_ctx = mbedtls_pk_ec( transparent_ctx );
211
212 CK_ASSERT( C_GetAttributeValue( hSession, hPublicKey,
213 public_attributes, ARRAY_LENGTH( public_attributes ) ) );
214 // TODO: lift out a function or two from pkparse.c
215 // * pk_get_ecparams followed by pk_use_ecparams for ecParams?
216 // * Some code from pk_group_from_specified to read an octet string for ecPoint?
217 {
218 mbedtls_asn1_buf params_asn1;
219 CK_ULONG ecParams_length = public_attributes[0].ulValueLen;
220 mbedtls_ecp_group_id grp_id;
221 params_asn1.tag = ecParams[0];
222 params_asn1.len = ecParams[1];
223 params_asn1.p = ecParams + 2;
224 TEST_ASSERT( ecParams_length == 2 + params_asn1.len );
225 TEST_ASSERT( mbedtls_oid_get_ec_grp( &params_asn1, &grp_id ) == 0 );
226 TEST_ASSERT( mbedtls_ecp_group_load( &ecp_ctx->grp, grp_id ) == 0 );
227 }
228 {
229 unsigned char *p = ecPoint;
230 size_t len;
231 CK_ULONG ecPoint_length = public_attributes[1].ulValueLen;
232 TEST_ASSERT( mbedtls_asn1_get_tag( &p,
233 ecPoint + ecPoint_length,
234 &len,
235 MBEDTLS_ASN1_OCTET_STRING ) == 0 );
236 TEST_ASSERT( mbedtls_ecp_point_read_binary( &ecp_ctx->grp,
237 &ecp_ctx->Q,
238 p, len ) == 0 );
239 }
240 }
241 break;
242#endif /* MBEDTLS_ECDSA_C */
243
244 default:
245 TEST_ASSERT( !"Unsupported key type in test data" );
246 break;
247 }
248
249 /* Sign with the token and verify in software */
250 TEST_ASSERT( mbedtls_pk_sign( &pkcs11_ctx, MBEDTLS_MD_SHA256,
251 hash_value, 32,
252 sig_buffer, &sig_length,
253 NULL, NULL ) == 0 );
254 TEST_ASSERT( mbedtls_pk_verify( &transparent_ctx, MBEDTLS_MD_SHA256,
255 hash_value, 32,
256 sig_buffer, sig_length ) == 0 );
257
258exit:
259 if( hPublicKey != CK_INVALID_HANDLE )
260 C_DestroyObject( hSession, hPublicKey );
261 if( hPrivateKey != CK_INVALID_HANDLE )
262 C_DestroyObject( hSession, hPrivateKey );
263 C_CloseSession( hSession );
264 C_Finalize( NULL_PTR );
265 mbedtls_pk_free( &pkcs11_ctx );
266 mbedtls_pk_free( &transparent_ctx );
267}
268/* END_CASE */
269
270/* BEGIN_CASE depends_on:MBEDTLS_PK_C:MBEDTLS_SHA256_C */
271void pk_import_sign( char *file )
272{
273 mbedtls_pk_context pkcs11_ctx;
274 mbedtls_pk_context transparent_ctx;
275 CK_SESSION_HANDLE hSession = CK_INVALID_HANDLE;
276 CK_OBJECT_HANDLE hPublicKey = CK_INVALID_HANDLE;
277 CK_OBJECT_HANDLE hPrivateKey = CK_INVALID_HANDLE;
278 unsigned char hash_value[32] = "Fake hash, it doesn't matter....";
279 unsigned char sig_buffer[4096];
280 size_t sig_length = sizeof( sig_buffer );
281
282 mbedtls_pk_init( &pkcs11_ctx );
283 mbedtls_pk_init( &transparent_ctx );
284
285 /* Read a transparent key */
286 TEST_ASSERT( mbedtls_pk_parse_keyfile( &transparent_ctx, file, NULL ) == 0 );
287
288 /* Initialize cryptoki and import the key into the token */
289 hSession = pkcs11_init( );
290 TEST_ASSERT( hSession != CK_INVALID_HANDLE );
291
292 TEST_ASSERT( mbedtls_pk_import_to_pkcs11( &transparent_ctx,
293 MBEDTLS_PK_FLAG_SIGN |
294 MBEDTLS_PK_FLAG_VERIFY,
295 hSession,
296 &hPublicKey,
297 &hPrivateKey ) == 0 );
298 TEST_ASSERT( hPublicKey != CK_INVALID_HANDLE );
299 TEST_ASSERT( hPrivateKey != CK_INVALID_HANDLE );
300 TEST_ASSERT( mbedtls_pk_setup_pkcs11( &pkcs11_ctx,
301 hSession,
302 hPublicKey,
303 hPrivateKey ) == 0 );
304
305 /* Sign with the token and verify in software */
306 TEST_ASSERT( sizeof( sig_buffer ) >= mbedtls_pk_signature_size( &pkcs11_ctx ) );
307 TEST_ASSERT( mbedtls_pk_sign( &pkcs11_ctx, MBEDTLS_MD_SHA256,
308 hash_value, 32,
309 sig_buffer, &sig_length,
310 NULL, NULL ) == 0 );
311 TEST_ASSERT( mbedtls_pk_verify( &transparent_ctx, MBEDTLS_MD_SHA256,
312 hash_value, 32,
313 sig_buffer, sig_length ) == 0 );
314
315exit:
316 if( hPublicKey != CK_INVALID_HANDLE )
317 C_DestroyObject( hSession, hPublicKey );
318 if( hPrivateKey != CK_INVALID_HANDLE )
319 C_DestroyObject( hSession, hPrivateKey );
320 C_CloseSession( hSession );
321 C_Finalize( NULL_PTR );
322 mbedtls_pk_free( &pkcs11_ctx );
323 mbedtls_pk_free( &transparent_ctx );
324}
325/* END_CASE */