1 /* -*- mode: c; c-file-style:"stroustrup"; -*- */
2
3 /*
4 * Copyright (c) 2018 Mastercard
5 *
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18
19
20 #include <config.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <stdlib.h>
24 #include "pkcs11lib.h"
25
26 /*
27 * idorlabel contains either CKA_ID or CKA_LABEL
28 */
29
pkcs11_getObjectHandle(pkcs11Context * p11Context,CK_OBJECT_CLASS oclass,CK_ATTRIBUTE_TYPE idorlabel,CK_BYTE_PTR byteArrayPtr,CK_ULONG byteArrayLen)30 CK_OBJECT_HANDLE pkcs11_getObjectHandle( pkcs11Context * p11Context, CK_OBJECT_CLASS oclass, CK_ATTRIBUTE_TYPE idorlabel, CK_BYTE_PTR byteArrayPtr, CK_ULONG byteArrayLen )
31 {
32 CK_RV rc;
33 CK_BBOOL token;
34 CK_ULONG objectCount = 0;
35 CK_ULONG oClassLen = sizeof( CK_OBJECT_CLASS );
36 CK_ULONG tokenLen = sizeof( CK_BBOOL );
37 CK_ULONG searchTemplateLen;
38 CK_OBJECT_HANDLE hObject;
39
40 CK_C_FindObjectsInit pC_FindObjectsInit;
41 CK_C_FindObjects pC_FindObjects;
42 CK_C_FindObjectsFinal pC_FindObjectsFinal;
43
44 pC_FindObjectsInit = p11Context->FunctionList.C_FindObjectsInit;
45 pC_FindObjects = p11Context->FunctionList.C_FindObjects;
46 pC_FindObjectsFinal = p11Context->FunctionList.C_FindObjectsFinal;
47
48 CK_ATTRIBUTE searchTemplate[] = {
49 { CKA_CLASS, NULL_PTR, 0x00 },
50 { idorlabel, NULL_PTR, 0x00 },
51 { CKA_TOKEN, NULL_PTR, 0x00 },
52 };
53
54 token = CK_TRUE;
55
56 searchTemplateLen = ( sizeof( searchTemplate ) / sizeof( CK_ATTRIBUTE ) );
57
58 searchTemplate[0].pValue = &oclass;
59 searchTemplate[0].ulValueLen = oClassLen;
60 searchTemplate[1].pValue = byteArrayPtr;
61 searchTemplate[1].ulValueLen = byteArrayLen;
62 searchTemplate[2].pValue = &token;
63 searchTemplate[2].ulValueLen = tokenLen;
64
65 if ( ( rc = pC_FindObjectsInit( p11Context->Session, searchTemplate, searchTemplateLen ) ) != CKR_OK )
66 {
67 pkcs11_error( rc, "C_FindObjectsInit" );
68 return ( CK_INVALID_HANDLE );
69 }
70
71 if ( ( rc = pC_FindObjects( p11Context->Session, &hObject, 1, &objectCount ) ) != CKR_OK )
72 {
73 pkcs11_error( rc, "C_FindObjects" );
74 return ( CK_INVALID_HANDLE );
75 }
76
77 if ( objectCount == 0 )
78 {
79 ( void ) fprintf( stdout, "No object found with matching CKA_ID and or CKA_CLASS\n" );
80 return ( CK_INVALID_HANDLE );
81 }
82
83 if ( ( rc = pC_FindObjectsFinal( p11Context->Session ) ) != CKR_OK )
84 pkcs11_error( rc, "C_FindObjectsFinal" );
85
86 return ( hObject );
87 }
88
89
pkcs11_adjust_des_key_parity(CK_BYTE * pucKey,int nKeyLen)90 void pkcs11_adjust_des_key_parity(CK_BYTE* pucKey, int nKeyLen)
91 {
92 int cPar;
93 int i, j;
94
95 for( i = 0; i < nKeyLen; i++)
96 {
97 cPar = 0;
98 for( j = 0; j < 8; j++) {
99 if(pucKey[i] & (001 << j))
100 cPar = !cPar;
101 }
102 if(!cPar)
103 pucKey[i] ^= 001;
104 }
105 }
106
107
108
pkcs11_getObjectAttributes(pkcs11Context * p11Context,CK_OBJECT_HANDLE objectHandle,CK_ATTRIBUTE attr[],int attrlen)109 int pkcs11_getObjectAttributes( pkcs11Context * p11Context, CK_OBJECT_HANDLE objectHandle, CK_ATTRIBUTE attr[], int attrlen )
110 {
111 CK_RV rc;
112 int i;
113
114 for(i=0; i<attrlen; i++) {
115 attr[i].pValue = NULL_PTR;
116 attr[i].ulValueLen = 0;
117 }
118
119 CK_C_GetAttributeValue pC_GetAttributeValue = p11Context->FunctionList.C_GetAttributeValue;
120
121
122 if ( ( rc = pC_GetAttributeValue( p11Context->Session, objectHandle, attr, attrlen ) ) == CKR_OK ) {
123 for(i=0; i<attrlen; i++) {
124 attr[i].pValue = malloc( attr[i].ulValueLen );
125 }
126 if( (rc = pC_GetAttributeValue( p11Context->Session, objectHandle, attr, attrlen ) ) != CKR_OK ) {
127 pkcs11_error( rc, "C_GetAttributeValue" );
128 for(i=0; i<attrlen; i++) {
129 free(attr[i].pValue);
130 attr[i].pValue = NULL_PTR;
131 }
132 }
133 } else {
134 pkcs11_error( rc, "C_GetAttributeValue" );
135 }
136 return rc;
137 }
138
pkcs11_freeObjectAttributesValues(CK_ATTRIBUTE attr[],int attrlen)139 void pkcs11_freeObjectAttributesValues( CK_ATTRIBUTE attr[], int attrlen)
140 {
141 int i;
142 for(i=0; i<attrlen; i++) {
143 if (attr[i].pValue != NULL_PTR) {
144 free(attr[i].pValue);
145 attr[i].pValue = NULL_PTR;
146 }
147 }
148 }
149
150
pkcs11_setObjectAttribute(pkcs11Context * p11Context,CK_OBJECT_HANDLE objectHandle,CK_ATTRIBUTE * attr)151 CK_RV pkcs11_setObjectAttribute( pkcs11Context * p11Context, CK_OBJECT_HANDLE objectHandle, CK_ATTRIBUTE *attr )
152 {
153 CK_RV rc;
154 CK_ULONG setTemplateLen;
155
156 CK_ATTRIBUTE setTemplate[] = {
157 { 0, NULL_PTR, 0 },
158 };
159
160 setTemplate[0] = *attr;
161 setTemplateLen = 1;
162
163 rc = p11Context->FunctionList.C_SetAttributeValue( p11Context->Session, objectHandle, setTemplate, setTemplateLen );
164
165 if ( rc != CKR_OK ) {
166 pkcs11_error( rc, "C_SetAttributeValue" );
167 }
168
169 return rc;
170 }
171
pkcs11_setObjectAttributes(pkcs11Context * p11Context,CK_OBJECT_HANDLE objectHandle,CK_ATTRIBUTE * attr,size_t cnt)172 CK_RV pkcs11_setObjectAttributes( pkcs11Context * p11Context, CK_OBJECT_HANDLE objectHandle, CK_ATTRIBUTE *attr, size_t cnt )
173 {
174 CK_RV rc;
175
176 rc = p11Context->FunctionList.C_SetAttributeValue( p11Context->Session, objectHandle, attr, cnt );
177
178 if ( rc != CKR_OK ) {
179 pkcs11_error( rc, "C_SetAttributeValue" );
180 }
181
182 return rc;
183 }
184
185
186 /* adjust CKA_ID for RSA key pair, to set it to SHA1(modulus) for RSA and SHA1(ec_point) for EC */
pkcs11_adjust_keypair_id(pkcs11Context * p11Context,CK_OBJECT_HANDLE hPublicKey,CK_OBJECT_HANDLE hPrivateKey)187 func_rc pkcs11_adjust_keypair_id(pkcs11Context * p11Context, CK_OBJECT_HANDLE hPublicKey, CK_OBJECT_HANDLE hPrivateKey)
188 {
189 func_rc rc = rc_error_other_error;
190
191 pkcs11AttrList *attrs;
192
193 attrs = pkcs11_new_attrlist(p11Context,
194 _ATTR(CKA_KEY_TYPE),
195 _ATTR(CKA_MODULUS),
196 _ATTR(CKA_EC_POINT),
197 _ATTR(CKA_VALUE),
198 _ATTR_END );
199
200 if( pkcs11_read_attr_from_handle_ext (attrs, hPublicKey,
201 CKR_FUNCTION_FAILED, /* workaround for nCipher bug 30966 */
202 0L ) == true) {
203 CK_ATTRIBUTE_PTR key_type, attr;
204
205 key_type = pkcs11_get_attr_in_attrlist ( attrs, CKA_KEY_TYPE );
206
207 switch(*(CK_KEY_TYPE *)(key_type->pValue)) {
208 /* if RSA, we hash the modulus */
209 case CKK_RSA:
210 attr = pkcs11_get_attr_in_attrlist ( attrs, CKA_MODULUS );
211 break;
212
213 /* if EC or Edwards, we hash the point */
214 case CKK_EC:
215 case CKK_EC_EDWARDS:
216 attr = pkcs11_get_attr_in_attrlist ( attrs, CKA_EC_POINT );
217 break;
218
219 /* if DSA or DH, we hash the public key */
220 case CKK_DSA:
221 case CKK_DH:
222 attr = pkcs11_get_attr_in_attrlist( attrs, CKA_VALUE );
223 break;
224 }
225
226 if(attr!=NULL) {
227 CK_ATTRIBUTE id_attr = {CKA_ID, NULL_PTR, 0 };
228 id_attr.ulValueLen = pkcs11_openssl_alloc_and_sha1( attr[0].pValue, attr[0].ulValueLen, &id_attr.pValue);
229 if(id_attr.ulValueLen>0) {
230 /* in the case of public key import, skip hPrivateKey */
231 if(hPrivateKey!=NULL_PTR) {
232 pkcs11_setObjectAttribute( p11Context, hPrivateKey, &id_attr );
233 };
234
235 if(hPublicKey!=NULL_PTR) {
236 pkcs11_setObjectAttribute( p11Context, hPublicKey, &id_attr );
237 } else {
238 fprintf(stderr, "Warning: no public key object found.");
239 }
240 }
241 rc = rc_ok;
242
243 if(id_attr.pValue != NULL_PTR) pkcs11_openssl_free(&id_attr.pValue);
244 pkcs11_delete_attrlist(attrs);
245
246 } else {
247 fprintf(stderr, "Warning: could not find a public value to hash for adjusting CKA_ID");
248 }
249 }
250 return rc;
251 }
252
253
254
pkcs11_get_object_size(pkcs11Context * p11ctx,CK_OBJECT_HANDLE obj)255 CK_ULONG pkcs11_get_object_size(pkcs11Context *p11ctx, CK_OBJECT_HANDLE obj)
256 {
257 CK_ULONG size = 0;
258 CK_RV rv ;
259
260 rv = p11ctx->FunctionList.C_GetObjectSize(p11ctx->Session, obj, &size);
261
262 if(rv!=CKR_OK) {
263 pkcs11_error(rv, "C_GetObjectSize");
264 }
265
266 return size;
267 }
268
269
pkcs11_is_mech_supported(pkcs11Context * p11Context,CK_MECHANISM_TYPE m)270 CK_BBOOL pkcs11_is_mech_supported(pkcs11Context *p11Context, CK_MECHANISM_TYPE m)
271 {
272 CK_BBOOL rv = CK_FALSE;
273
274 CK_MECHANISM_TYPE_PTR mechlist = NULL_PTR;
275 CK_ULONG mechlist_len = 0L, i;
276
277 if(p11Context!=NULL) {
278
279 if (( rv = p11Context->FunctionList.C_GetMechanismList( p11Context->slot, NULL_PTR, &mechlist_len ) ) != CKR_OK ) {
280 pkcs11_error( rv, "C_GetMechanismList" );
281 goto error;
282 }
283
284 mechlist=calloc( mechlist_len, sizeof(CK_MECHANISM_TYPE) );
285
286 if(mechlist==NULL) {
287 fprintf(stderr, "Ouch, memory error.\n");
288 goto error;
289 }
290
291 if (( rv = p11Context->FunctionList.C_GetMechanismList( p11Context->slot, mechlist, &mechlist_len ) ) != CKR_OK ) {
292 pkcs11_error( rv, "C_GetMechanismList" );
293 goto error;
294 }
295
296 for(i=0;i<mechlist_len;i++) {
297 if(mechlist[i]==m) {
298 rv = CK_TRUE;
299 break;
300 }
301 }
302 }
303
304 error:
305 if(mechlist!=NULL) free(mechlist);
306
307 return rv;
308 }
309
310
311
pkcs11_get_rsa_modulus_bits(pkcs11Context * p11Context,CK_OBJECT_HANDLE hndl)312 int pkcs11_get_rsa_modulus_bits(pkcs11Context *p11Context, CK_OBJECT_HANDLE hndl)
313 {
314 int rv=0;
315 pkcs11AttrList *attrs = NULL;
316
317 attrs = pkcs11_new_attrlist(p11Context, _ATTR(CKA_MODULUS), _ATTR_END );
318
319 if(attrs) {
320
321 if( pkcs11_read_attr_from_handle (attrs, hndl) == true) {
322 CK_ATTRIBUTE_PTR modulus = pkcs11_get_attr_in_attrlist ( attrs, CKA_MODULUS );
323 rv = (modulus->ulValueLen)<<3; /* this could be wrong, not bit-accurate */
324 }
325
326 pkcs11_delete_attrlist(attrs);
327 }
328
329 return rv;
330 }
331
332
pkcs11_get_dsa_pubkey_bits(pkcs11Context * p11Context,CK_OBJECT_HANDLE hndl)333 int pkcs11_get_dsa_pubkey_bits(pkcs11Context *p11Context, CK_OBJECT_HANDLE hndl)
334 {
335 int rv=0;
336 pkcs11AttrList *attrs = NULL;
337
338 attrs = pkcs11_new_attrlist(p11Context, _ATTR(CKA_VALUE), _ATTR_END );
339
340 if(attrs) {
341
342 if( pkcs11_read_attr_from_handle (attrs, hndl) == true) {
343 CK_ATTRIBUTE_PTR pubkey = pkcs11_get_attr_in_attrlist ( attrs, CKA_VALUE );
344 rv = (pubkey->ulValueLen)<<3; /* this could be wrong, not bit-accurate */
345 }
346
347 pkcs11_delete_attrlist(attrs);
348 }
349
350 return rv;
351 }
352
353
pkcs11_get_object_class(pkcs11Context * p11Context,CK_OBJECT_HANDLE hndl)354 CK_OBJECT_CLASS pkcs11_get_object_class(pkcs11Context *p11Context, CK_OBJECT_HANDLE hndl)
355 {
356 CK_OBJECT_CLASS rv = 0xFFFFFFFFUL; /* synthetic value, means "error" */
357
358 pkcs11AttrList *attrs = NULL;
359
360 /* extract object class from provided handle */
361 attrs = pkcs11_new_attrlist(p11Context, _ATTR(CKA_CLASS), _ATTR_END );
362
363 if(attrs) {
364
365 if( pkcs11_read_attr_from_handle (attrs, hndl) == true) {
366 CK_ATTRIBUTE_PTR attr_ptr = pkcs11_get_attr_in_attrlist(attrs, CKA_CLASS);
367 rv = *(CK_OBJECT_CLASS *)(attr_ptr->pValue);
368 }
369
370 pkcs11_delete_attrlist(attrs);
371 }
372
373 return rv;
374 }
375
pkcs11_get_key_type(pkcs11Context * p11Context,CK_OBJECT_HANDLE hndl)376 key_type_t pkcs11_get_key_type(pkcs11Context *p11Context, CK_OBJECT_HANDLE hndl)
377 {
378 key_type_t rv = unknown;
379
380 pkcs11AttrList *attrs = NULL;
381
382 typedef struct {
383 CK_KEY_TYPE p11_key_type;
384 key_type_t key_type;
385 } key_type_mapping_t;
386
387 static const key_type_mapping_t key_type_mapping[] = {
388 { CKK_AES, aes, },
389 { CKK_DES, des, },
390 { CKK_DES2, des2, }, /* des3 double length */
391 { CKK_DES3, des3, }, /* des3 triple length */
392 { CKK_RSA, rsa, },
393 { CKK_EC, ec, },
394 { CKK_EC_EDWARDS, ed },
395 { CKK_DSA, dsa, },
396 { CKK_DH, dh, },
397 { CKK_GENERIC_SECRET, generic, },
398 #if defined(HAVE_NCIPHER)
399 { CKK_SHA_1_HMAC, hmacsha1, },
400 { CKK_SHA224_HMAC, hmacsha224, },
401 { CKK_SHA256_HMAC, hmacsha256, },
402 { CKK_SHA384_HMAC, hmacsha384, },
403 { CKK_SHA512_HMAC, hmacsha512 },
404 #endif
405 };
406
407 /* extract object class from provided handle */
408 attrs = pkcs11_new_attrlist(p11Context, _ATTR(CKA_KEY_TYPE), _ATTR_END );
409
410 if(attrs) {
411
412 if( pkcs11_read_attr_from_handle (attrs, hndl) == true) {
413 CK_ATTRIBUTE_PTR attr_ptr = pkcs11_get_attr_in_attrlist(attrs, CKA_KEY_TYPE);
414 int i;
415 for(i=0; i<sizeof key_type_mapping / sizeof(key_type_mapping_t); i++) {
416 if(*(CK_KEY_TYPE *)(attr_ptr->pValue)==key_type_mapping[i].p11_key_type) {
417 rv = key_type_mapping[i].key_type;
418 break;
419 }
420 }
421 }
422
423 pkcs11_delete_attrlist(attrs);
424 }
425
426 return rv;
427 }
428
429 /* this function returns an allocated buffer to CKA_LABEL if found */
pkcs11_alloclabelforhandle(pkcs11Context * p11Context,CK_OBJECT_HANDLE hndl)430 char *pkcs11_alloclabelforhandle(pkcs11Context *p11Context, CK_OBJECT_HANDLE hndl)
431 {
432 pkcs11AttrList *attrs = NULL;
433 char *label = NULL;
434
435 attrs = pkcs11_new_attrlist(p11Context, _ATTR(CKA_LABEL), _ATTR_END );
436
437 if(attrs) {
438 if( pkcs11_read_attr_from_handle (attrs, hndl) == true) {
439 CK_ATTRIBUTE_PTR attr_ptr = pkcs11_get_attr_in_attrlist(attrs, CKA_LABEL);
440 if(attr_ptr) {
441 label = malloc( attr_ptr->ulValueLen+1 );
442 if(label) {
443 memcpy( label, attr_ptr->pValue, attr_ptr->ulValueLen);
444 label[attr_ptr->ulValueLen]=0; /* end the string */
445 }
446 }
447 }
448 pkcs11_delete_attrlist(attrs); /* cleanup after use */
449 }
450
451 return label;
452 }
453
454
455 /**************************************************************************/
456
457