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 <stdarg.h>
25 #include "pkcs11lib.h"
26 
27 
28 #define P11SEARCH_NUM_HANDLES 64
29 
30 
pkcs11_new_search(pkcs11Context * p11Context,CK_ATTRIBUTE_PTR search,CK_ULONG length)31 pkcs11Search * pkcs11_new_search( pkcs11Context *p11Context, CK_ATTRIBUTE_PTR search, CK_ULONG length)
32 {
33     pkcs11Search *p11s = NULL;
34     CK_RV retCode;
35 
36     p11s = calloc(1, sizeof(pkcs11Search));
37 
38     if(p11s==NULL) {
39 	fprintf(stderr, "Error: Can't allocate memory for pkcs11Search structure");
40 	goto error;
41     }
42 
43     p11s->p11Context = p11Context;
44     p11s->FindObjectsInit  = p11Context->FunctionList.C_FindObjectsInit;
45     p11s->FindObjects      = p11Context->FunctionList.C_FindObjects;
46     p11s->FindObjectsFinal = p11Context->FunctionList.C_FindObjectsFinal;
47 
48     p11s->handle_array = calloc( P11SEARCH_NUM_HANDLES, sizeof (CK_OBJECT_HANDLE));
49 
50     if(p11s->handle_array==NULL) {
51 	fprintf(stderr, "Error: Can't allocate memory for pkcs11Search handle array");
52 	goto error;
53     }
54 
55     p11s->allocated = P11SEARCH_NUM_HANDLES;
56     p11s->count = p11s->index = 0;
57 
58 
59     if ( ( retCode = p11s->FindObjectsInit( p11Context->Session, search, length ) ) != CKR_OK )
60     {
61 	pkcs11_error( retCode, "C_FindObjectsInit" );
62 	goto error;
63     }
64 
65     return p11s;
66 
67 error:
68     if(p11s) {
69 	if(p11s->handle_array) {
70 	    free(p11s->handle_array);
71 	    p11s->handle_array=NULL;
72 	}
73 	free(p11s);
74 	p11s = NULL;
75     }
76 
77     return p11s;
78 }
79 
80 
pkcs11_new_search_from_idtemplate(pkcs11Context * p11Context,pkcs11IdTemplate * idtmpl)81 pkcs11Search * pkcs11_new_search_from_idtemplate( pkcs11Context *p11Context, pkcs11IdTemplate *idtmpl)
82 {
83     pkcs11Search *p11s = NULL;
84 
85     if(p11Context && idtmpl) {
86 	p11s = pkcs11_new_search(p11Context, idtmpl->template, idtmpl->template_len);
87     }
88     return p11s;
89 }
90 
91 
92 
pkcs11_fetch_next(pkcs11Search * p11s)93 CK_OBJECT_HANDLE pkcs11_fetch_next(pkcs11Search *p11s)
94 {
95 
96     CK_OBJECT_HANDLE rv = 0;
97 
98     if(p11s) {
99 	/* have we ever executed FindObjects? */
100 	if(p11s->count==0 || (p11s->count>0 && p11s->index==p11s->count) ) {
101 	    CK_RV retCode;
102 
103 	    if ( ( retCode = p11s->FindObjects( p11s->p11Context->Session,
104 						p11s->handle_array,
105 						p11s->allocated,
106 						&(p11s->count)  ) ) != CKR_OK )
107 	    {
108 		pkcs11_error( retCode, "C_FindObjects" );
109 		return NULL_PTR;
110 	    }
111 	    p11s->index=0;		/* reset index */
112 	}
113 
114 	if(p11s->count>0 && p11s->index < p11s->count) {
115 	    rv = p11s->handle_array[p11s->index++];
116 	}
117     }
118     return rv;
119 
120 }
121 
122 
pkcs11_delete_search(pkcs11Search * p11s)123 void pkcs11_delete_search(pkcs11Search *p11s)
124 {
125 
126     if(p11s) {
127 	CK_RV retCode;
128 
129 	if ( ( retCode = p11s->FindObjectsFinal( p11s->p11Context->Session ) ) != CKR_OK ) {
130 	    pkcs11_error( retCode, "C_FindObjectsFinal" );
131 	}
132 
133 	if(p11s->handle_array) {
134 	    free(p11s->handle_array);
135 	    p11s->handle_array=NULL;
136 	}
137 	free(p11s);
138 	p11s = NULL;
139     }
140 }
141 
142 
143 /* high-level search functions */
144 
pkcs11_object_with_class_exists(pkcs11Context * p11Context,char * label,CK_OBJECT_CLASS cla)145 static int pkcs11_object_with_class_exists(pkcs11Context *p11Context, char *label, CK_OBJECT_CLASS cla)
146 {
147 
148     int rv=0;
149     pkcs11Search *search=NULL;
150     CK_OBJECT_CLASS oclass = cla;
151 
152     CK_ATTRIBUTE searchTemplate[] = {
153 	{ CKA_CLASS, &oclass, sizeof oclass },
154 	{ CKA_LABEL, label, strlen(label) },
155     };
156 
157     search = pkcs11_new_search( p11Context, searchTemplate, sizeof(searchTemplate) / sizeof(CK_ATTRIBUTE) );
158 
159 
160     if(search) {		/* we just need one hit */
161 	rv = pkcs11_fetch_next(search)!=0 ? 1 : 0 ;
162 	pkcs11_delete_search(search);
163     }
164 
165     return rv;
166 }
167 
pkcs11_find_object_with_class(pkcs11Context * p11Context,char * label,CK_OBJECT_CLASS cla)168 static CK_OBJECT_HANDLE pkcs11_find_object_with_class(pkcs11Context *p11Context, char *label, CK_OBJECT_CLASS cla)
169 {
170 
171     pkcs11Search *search=NULL;
172     CK_OBJECT_CLASS oclass = cla;
173     CK_OBJECT_HANDLE hndl=NULL_PTR;
174 
175     CK_ATTRIBUTE searchTemplate[] = {
176 	{ CKA_CLASS, &oclass, sizeof oclass },
177 	{ CKA_LABEL, label, strlen(label) },
178     };
179 
180     search = pkcs11_new_search( p11Context, searchTemplate, sizeof(searchTemplate) / sizeof(CK_ATTRIBUTE) );
181 
182 
183     if(search) {		/* we stop by the first hit */
184 
185 	hndl = pkcs11_fetch_next(search);
186 
187 	pkcs11_delete_search(search);
188 
189     }
190 
191     return hndl;
192 }
193 
194 
pkcs11_label_exists(pkcs11Context * p11Context,char * label)195 int pkcs11_label_exists(pkcs11Context *p11Context, char *label)
196 {
197 
198     int rv=0;
199     pkcs11Search *search=NULL;
200     CK_ATTRIBUTE searchTemplate[] = {
201 	{ CKA_LABEL, label, strlen(label) },
202     };
203 
204     search = pkcs11_new_search( p11Context, searchTemplate, sizeof(searchTemplate) / sizeof(CK_ATTRIBUTE) );
205 
206 
207     if(search) {		/* we just need one hit */
208 	rv = pkcs11_fetch_next(search)!=0 ? 1 : 0 ;
209 	pkcs11_delete_search(search);
210     }
211 
212     return rv;
213 }
214 
215 
pkcs11_privatekey_exists(pkcs11Context * p11Context,char * label)216 inline int pkcs11_privatekey_exists(pkcs11Context *p11Context, char *label)
217 {
218     return pkcs11_object_with_class_exists(p11Context, label, CKO_PRIVATE_KEY);
219 }
220 
pkcs11_publickey_exists(pkcs11Context * p11Context,char * label)221 inline int pkcs11_publickey_exists(pkcs11Context *p11Context, char *label)
222 {
223     return pkcs11_object_with_class_exists(p11Context, label, CKO_PUBLIC_KEY);
224 }
225 
pkcs11_secretkey_exists(pkcs11Context * p11Context,char * label)226 inline int pkcs11_secretkey_exists(pkcs11Context *p11Context, char *label)
227 {
228     return pkcs11_object_with_class_exists(p11Context, label, CKO_SECRET_KEY);
229 }
230 
pkcs11_certificate_exists(pkcs11Context * p11Context,char * label)231 inline int pkcs11_certificate_exists(pkcs11Context *p11Context, char *label)
232 {
233     return pkcs11_object_with_class_exists(p11Context, label, CKO_CERTIFICATE);
234 }
235 
pkcs11_data_exists(pkcs11Context * p11Context,char * label)236 inline int pkcs11_data_exists(pkcs11Context *p11Context, char *label)
237 {
238     return pkcs11_object_with_class_exists(p11Context, label, CKO_DATA);
239 }
240 
241 
pkcs11_findkeypair(pkcs11Context * p11Context,char * label,CK_OBJECT_HANDLE_PTR hPublicKey,CK_OBJECT_HANDLE_PTR hPrivateKey)242 int pkcs11_findkeypair(pkcs11Context *p11Context, char *label, CK_OBJECT_HANDLE_PTR hPublicKey, CK_OBJECT_HANDLE_PTR hPrivateKey)
243 {
244 
245     int rv=0;
246 
247     *hPrivateKey = pkcs11_find_object_with_class(p11Context, label, CKO_PRIVATE_KEY);
248     *hPublicKey  = pkcs11_find_object_with_class(p11Context, label, CKO_PUBLIC_KEY);
249 
250     /* we need hPrivateKey. hPublicKey is optional. */
251     if (*hPrivateKey != NULL_PTR) {
252 	rv++;
253 	if (*hPublicKey != NULL_PTR) {
254 	    rv++;
255 	} else {
256 	    fprintf(stderr, "Warning: no public key object found for label '%s'\n", label);
257 	}
258     }
259 
260     return rv;
261 }
262 
pkcs11_findpublickey(pkcs11Context * p11Context,char * label,CK_OBJECT_HANDLE_PTR hPublicKey)263 int pkcs11_findpublickey(pkcs11Context *p11Context, char *label, CK_OBJECT_HANDLE_PTR hPublicKey)
264 {
265 
266     int rv=0;
267 
268     *hPublicKey  = pkcs11_find_object_with_class(p11Context, label, CKO_PUBLIC_KEY);
269 
270     rv = *hPublicKey!=0;
271 
272     return rv;
273 }
274 
pkcs11_findprivatekey(pkcs11Context * p11Context,char * label,CK_OBJECT_HANDLE_PTR hPrivateKey)275 int pkcs11_findprivatekey(pkcs11Context *p11Context, char *label, CK_OBJECT_HANDLE_PTR hPrivateKey)
276 {
277 
278     int rv=0;
279 
280     *hPrivateKey  = pkcs11_find_object_with_class(p11Context, label, CKO_PRIVATE_KEY);
281 
282     rv = *hPrivateKey!=0;
283 
284     return rv;
285 }
286 
pkcs11_findsecretkey(pkcs11Context * p11Context,char * label,CK_OBJECT_HANDLE_PTR hSecretKey)287 int pkcs11_findsecretkey(pkcs11Context *p11Context, char *label, CK_OBJECT_HANDLE_PTR hSecretKey)
288 {
289 
290     int rv=0;
291 
292     *hSecretKey = pkcs11_find_object_with_class(p11Context, label, CKO_SECRET_KEY);
293 
294     rv = *hSecretKey!=0;
295 
296     return rv;
297 }
298 
pkcs11_findprivateorsecretkey(pkcs11Context * p11Context,char * label,CK_OBJECT_HANDLE_PTR hKey,CK_OBJECT_CLASS * oclass)299 int pkcs11_findprivateorsecretkey(pkcs11Context *p11Context, char *label, CK_OBJECT_HANDLE_PTR hKey, CK_OBJECT_CLASS *oclass)
300 {
301 
302     int rv=0;
303 
304     *hKey  = pkcs11_find_object_with_class(p11Context, label, CKO_PRIVATE_KEY);
305 
306     if(*hKey) {
307 	/* good, we have our private key */
308 	*oclass = CKO_PRIVATE_KEY;
309 
310     } else {
311 	*hKey  = pkcs11_find_object_with_class(p11Context, label, CKO_SECRET_KEY);
312 
313 	if(*hKey) {
314 	    /* good, we have our secret key */
315 	    *oclass = CKO_SECRET_KEY;
316 	}
317     }
318 
319     rv = *hKey!=0;
320 
321     return rv;
322 }
323 
324 
325 /* EOF */
326