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