1 /* libp11, a simple layer on to of PKCS#11 API
2  * Copyright (C) 2005 Olaf Kirch <okir@lst.de>
3  * Copyright (C) 2016-2018 Michał Trojnara <Michal.Trojnara@stunnel.org>
4  *
5  *  This library is free software; you can redistribute it and/or
6  *  modify it under the terms of the GNU Lesser General Public
7  *  License as published by the Free Software Foundation; either
8  *  version 2.1 of the License, or (at your option) any later version.
9  *
10  *  This library is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13  *  Lesser General Public License for more details.
14  *
15  *  You should have received a copy of the GNU Lesser General Public
16  *  License along with this library; if not, write to the Free Software
17  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307  USA
18  */
19 
20 /*
21  * p11_cert.c - Handle certificates residing on a PKCS11 token
22  *
23  * Copyright (C) 2002, Olaf Kirch <okir@lst.de>
24  */
25 
26 #include "libp11-int.h"
27 #include <string.h>
28 
29 static int pkcs11_find_certs(PKCS11_TOKEN *);
30 static int pkcs11_next_cert(PKCS11_CTX *, PKCS11_TOKEN *, CK_SESSION_HANDLE);
31 static int pkcs11_init_cert(PKCS11_CTX *ctx, PKCS11_TOKEN *token,
32 	CK_SESSION_HANDLE session, CK_OBJECT_HANDLE o, PKCS11_CERT **);
33 
34 /*
35  * Enumerate all certs on the card
36  */
pkcs11_enumerate_certs(PKCS11_TOKEN * token,PKCS11_CERT ** certp,unsigned int * countp)37 int pkcs11_enumerate_certs(PKCS11_TOKEN *token,
38 		PKCS11_CERT **certp, unsigned int *countp)
39 {
40 	PKCS11_SLOT *slot = TOKEN2SLOT(token);
41 	PKCS11_CTX *ctx = SLOT2CTX(slot);
42 	PKCS11_TOKEN_private *tpriv = PRIVTOKEN(token);
43 	PKCS11_SLOT_private *spriv = PRIVSLOT(slot);
44 	PKCS11_CTX_private *cpriv = PRIVCTX(ctx);
45 	int rv;
46 
47 	/* Make sure we have a session */
48 	if (!spriv->haveSession && PKCS11_open_session(slot, 0))
49 		return -1;
50 
51 	CRYPTO_THREAD_write_lock(cpriv->rwlock);
52 	rv = pkcs11_find_certs(token);
53 	CRYPTO_THREAD_unlock(cpriv->rwlock);
54 	if (rv < 0) {
55 		pkcs11_destroy_certs(token);
56 		return -1;
57 	}
58 
59 	if (certp)
60 		*certp = tpriv->certs;
61 	if (countp)
62 		*countp = tpriv->ncerts;
63 	return 0;
64 }
65 
66 /**
67  * Remove a certificate from the associated token
68  */
pkcs11_remove_certificate(PKCS11_CERT * cert)69 int pkcs11_remove_certificate(PKCS11_CERT *cert){
70 	PKCS11_SLOT *slot = CERT2SLOT(cert);
71 	PKCS11_CTX *ctx = CERT2CTX(cert);
72 	PKCS11_SLOT_private *spriv = PRIVSLOT(slot);
73 	CK_OBJECT_HANDLE obj;
74 	CK_ULONG count;
75 	CK_ATTRIBUTE search_parameters[32];
76 	unsigned int n = 0;
77 	int rv;
78 
79 	/* First, make sure we have a session */
80 	if (!spriv->haveSession && PKCS11_open_session(slot, 1)){
81 		return -1;
82 	}
83 
84 	pkcs11_addattr_int(search_parameters + n++, CKA_CLASS, CKO_CERTIFICATE);
85 	if (cert->id && cert->id_len){
86 		pkcs11_addattr(search_parameters + n++, CKA_ID, cert->id, cert->id_len);
87 	}
88 	if (cert->label){
89 	 	pkcs11_addattr_s(search_parameters + n++, CKA_LABEL, cert->label);
90 	}
91 
92 	rv = CRYPTOKI_call(ctx,
93 		C_FindObjectsInit(spriv->session, search_parameters, n));
94 	CRYPTOKI_checkerr(CKR_F_PKCS11_REMOVE_CERTIFICATE, rv);
95 
96 	rv = CRYPTOKI_call(ctx, C_FindObjects(spriv->session, &obj, 1, &count));
97 	CRYPTOKI_checkerr(CKR_F_PKCS11_REMOVE_CERTIFICATE, rv);
98 
99 	CRYPTOKI_call(ctx, C_FindObjectsFinal(spriv->session));
100 	if (count!=1){
101 		pkcs11_zap_attrs(search_parameters, n);
102 		return -1;
103 	}
104 	rv = CRYPTOKI_call(ctx, C_DestroyObject(spriv->session, obj));
105 	if (rv != CKR_OK){
106 		pkcs11_zap_attrs(search_parameters, n);
107 		return -1;
108 	}
109 	pkcs11_zap_attrs(search_parameters, n);
110 	return 0;
111 }
112 
113 /*
114  * Find certificate matching a key
115  */
pkcs11_find_certificate(PKCS11_KEY * key)116 PKCS11_CERT *pkcs11_find_certificate(PKCS11_KEY *key)
117 {
118 	PKCS11_KEY_private *kpriv;
119 	PKCS11_CERT_private *cpriv;
120 	PKCS11_CERT *cert;
121 	unsigned int n, count;
122 
123 	kpriv = PRIVKEY(key);
124 	if (PKCS11_enumerate_certs(KEY2TOKEN(key), &cert, &count))
125 		return NULL;
126 	for (n = 0; n < count; n++, cert++) {
127 		cpriv = PRIVCERT(cert);
128 		if (cpriv->id_len == kpriv->id_len
129 				&& !memcmp(cpriv->id, kpriv->id, kpriv->id_len))
130 			return cert;
131 	}
132 	return NULL;
133 }
134 
135 /*
136  * Find all certs of a given type (public or private)
137  */
pkcs11_find_certs(PKCS11_TOKEN * token)138 static int pkcs11_find_certs(PKCS11_TOKEN *token)
139 {
140 	PKCS11_SLOT *slot = TOKEN2SLOT(token);
141 	PKCS11_CTX *ctx = SLOT2CTX(slot);
142 	PKCS11_SLOT_private *spriv = PRIVSLOT(slot);
143 	CK_OBJECT_CLASS cert_search_class;
144 	CK_ATTRIBUTE cert_search_attrs[] = {
145 		{CKA_CLASS, &cert_search_class, sizeof(cert_search_class)},
146 	};
147 	int rv, res = -1;
148 
149 	/* Tell the PKCS11 lib to enumerate all matching objects */
150 	cert_search_class = CKO_CERTIFICATE;
151 	rv = CRYPTOKI_call(ctx, C_FindObjectsInit(spriv->session, cert_search_attrs, 1));
152 	CRYPTOKI_checkerr(CKR_F_PKCS11_FIND_CERTS, rv);
153 
154 	do {
155 		res = pkcs11_next_cert(ctx, token, spriv->session);
156 	} while (res == 0);
157 
158 	CRYPTOKI_call(ctx, C_FindObjectsFinal(spriv->session));
159 
160 	return (res < 0) ? -1 : 0;
161 }
162 
pkcs11_next_cert(PKCS11_CTX * ctx,PKCS11_TOKEN * token,CK_SESSION_HANDLE session)163 static int pkcs11_next_cert(PKCS11_CTX *ctx, PKCS11_TOKEN *token,
164 		CK_SESSION_HANDLE session)
165 {
166 	CK_OBJECT_HANDLE obj;
167 	CK_ULONG count;
168 	int rv;
169 
170 	/* Get the next matching object */
171 	rv = CRYPTOKI_call(ctx, C_FindObjects(session, &obj, 1, &count));
172 	CRYPTOKI_checkerr(CKR_F_PKCS11_NEXT_CERT, rv);
173 
174 	if (count == 0)
175 		return 1;
176 
177 	if (pkcs11_init_cert(ctx, token, session, obj, NULL))
178 		return -1;
179 
180 	return 0;
181 }
182 
pkcs11_init_cert(PKCS11_CTX * ctx,PKCS11_TOKEN * token,CK_SESSION_HANDLE session,CK_OBJECT_HANDLE obj,PKCS11_CERT ** ret)183 static int pkcs11_init_cert(PKCS11_CTX *ctx, PKCS11_TOKEN *token,
184 		CK_SESSION_HANDLE session, CK_OBJECT_HANDLE obj, PKCS11_CERT ** ret)
185 {
186 	PKCS11_TOKEN_private *tpriv;
187 	PKCS11_CERT_private *cpriv;
188 	PKCS11_CERT *cert, *tmp;
189 	unsigned char *data;
190 	CK_CERTIFICATE_TYPE cert_type;
191 	size_t size;
192 	int i;
193 
194 	(void)ctx;
195 	(void)session;
196 
197 	/* Ignore unknown certificate types */
198 	size = sizeof(CK_CERTIFICATE_TYPE);
199 	if (pkcs11_getattr_var(token, obj, CKA_CERTIFICATE_TYPE, (CK_BYTE *)&cert_type, &size))
200 		return -1;
201 	if (cert_type != CKC_X_509)
202 		return 0;
203 
204 	/* Prevent re-adding existing PKCS#11 object handles */
205 	/* TODO: Rewrite the O(n) algorithm as O(log n),
206 	 * or it may be too slow with a large number of certificates */
207 	for (i=0; i < PRIVTOKEN(token)->ncerts; ++i)
208 		if (PRIVCERT(PRIVTOKEN(token)->certs + i)->object == obj)
209 			return 0;
210 
211 	/* Allocate memory */
212 	cpriv = OPENSSL_malloc(sizeof(PKCS11_CERT_private));
213 	if (!cpriv)
214 		return -1;
215 	memset(cpriv, 0, sizeof(PKCS11_CERT_private));
216 	tpriv = PRIVTOKEN(token);
217 	tmp = OPENSSL_realloc(tpriv->certs,
218 		(tpriv->ncerts + 1) * sizeof(PKCS11_CERT));
219 	if (!tmp)
220 		return -1;
221 	tpriv->certs = tmp;
222 	cert = tpriv->certs + tpriv->ncerts++;
223 	memset(cert, 0, sizeof(PKCS11_CERT));
224 
225 	/* Fill public properties */
226 	pkcs11_getattr_alloc(token, obj, CKA_LABEL, (CK_BYTE **)&cert->label, NULL);
227 	size = 0;
228 	if (!pkcs11_getattr_alloc(token, obj, CKA_VALUE, &data, &size)) {
229 		const unsigned char *p = data;
230 
231 		cert->x509 = d2i_X509(NULL, &p, (long)size);
232 		OPENSSL_free(data);
233 	}
234 	cert->id_len = 0;
235 	pkcs11_getattr_alloc(token, obj, CKA_ID, &cert->id, &cert->id_len);
236 
237 	/* Fill private properties */
238 	cert->_private = cpriv;
239 	cpriv->object = obj;
240 	cpriv->parent = token;
241 	cpriv->id_len = sizeof cpriv->id;
242 	if (pkcs11_getattr_var(token, obj, CKA_ID, cpriv->id, &cpriv->id_len))
243 		cpriv->id_len = 0;
244 
245 	if (ret)
246 		*ret = cert;
247 	return 0;
248 }
249 
250 /*
251  * Destroy all certs
252  */
pkcs11_destroy_certs(PKCS11_TOKEN * token)253 void pkcs11_destroy_certs(PKCS11_TOKEN *token)
254 {
255 	PKCS11_TOKEN_private *tpriv = PRIVTOKEN(token);
256 
257 	while (tpriv->ncerts > 0) {
258 		PKCS11_CERT *cert = &tpriv->certs[--(tpriv->ncerts)];
259 
260 		if (cert->x509)
261 			X509_free(cert->x509);
262 		OPENSSL_free(cert->label);
263 		if (cert->id)
264 			OPENSSL_free(cert->id);
265 		if (cert->_private)
266 			OPENSSL_free(cert->_private);
267 	}
268 	if (tpriv->certs)
269 		OPENSSL_free(tpriv->certs);
270 	tpriv->certs = NULL;
271 	tpriv->ncerts = 0;
272 }
273 
274 /*
275  * Store certificate
276  */
pkcs11_store_certificate(PKCS11_TOKEN * token,X509 * x509,char * label,unsigned char * id,size_t id_len,PKCS11_CERT ** ret_cert)277 int pkcs11_store_certificate(PKCS11_TOKEN *token, X509 *x509, char *label,
278 		unsigned char *id, size_t id_len, PKCS11_CERT ** ret_cert)
279 {
280 	PKCS11_SLOT *slot = TOKEN2SLOT(token);
281 	PKCS11_CTX *ctx = SLOT2CTX(slot);
282 	PKCS11_SLOT_private *spriv = PRIVSLOT(slot);
283 	CK_OBJECT_HANDLE object;
284 	CK_ATTRIBUTE attrs[32];
285 	unsigned int n = 0;
286 	int rv;
287 	int signature_nid;
288 	const EVP_MD* evp_md;
289 	CK_MECHANISM_TYPE ckm_md;
290 	unsigned char md[EVP_MAX_MD_SIZE];
291 	unsigned int md_len;
292 
293 	/* First, make sure we have a session */
294 	if (!PRIVSLOT(slot)->haveSession && PKCS11_open_session(slot, 1))
295 		return -1;
296 
297 	/* Now build the template */
298 	pkcs11_addattr_int(attrs + n++, CKA_CLASS, CKO_CERTIFICATE);
299 	pkcs11_addattr_bool(attrs + n++, CKA_TOKEN, TRUE);
300 	pkcs11_addattr_int(attrs + n++, CKA_CERTIFICATE_TYPE, CKC_X_509);
301 	pkcs11_addattr_obj(attrs + n++, CKA_SUBJECT,
302 		(pkcs11_i2d_fn)i2d_X509_NAME, X509_get_subject_name(x509));
303 	pkcs11_addattr_obj(attrs + n++, CKA_ISSUER,
304 		(pkcs11_i2d_fn)i2d_X509_NAME, X509_get_issuer_name(x509));
305 
306 	/* Get digest algorithm from x509 certificate */
307 #if OPENSSL_VERSION_NUMBER >= 0x10002000L && !defined(LIBRESSL_VERSION_NUMBER)
308 	signature_nid = X509_get_signature_nid(x509);
309 #else
310 	signature_nid = OBJ_obj2nid(x509->sig_alg->algorithm);
311 #endif
312 	evp_md = EVP_get_digestbynid(signature_nid);
313 	switch (EVP_MD_type(evp_md)) {
314 	default:
315 	case NID_sha1:
316 		ckm_md = CKM_SHA_1;
317 		break;
318 	case NID_sha224:
319 		ckm_md = CKM_SHA224;
320 		break;
321 	case NID_sha256:
322 		ckm_md = CKM_SHA256;
323 		break;
324 	case NID_sha512:
325 		ckm_md = CKM_SHA512;
326 		break;
327 	case NID_sha384:
328 		ckm_md = CKM_SHA384;
329 		break;
330 	}
331 
332 	/* Set hash algorithm; default is SHA-1 */
333 	pkcs11_addattr_int(attrs + n++, CKA_NAME_HASH_ALGORITHM, ckm_md);
334 	if(X509_pubkey_digest(x509,evp_md,md,&md_len))
335 		pkcs11_addattr(attrs + n++, CKA_HASH_OF_SUBJECT_PUBLIC_KEY,md,md_len);
336 
337 	pkcs11_addattr_obj(attrs + n++, CKA_VALUE, (pkcs11_i2d_fn)i2d_X509, x509);
338 	if (label)
339 		pkcs11_addattr_s(attrs + n++, CKA_LABEL, label);
340 	if (id && id_len)
341 		pkcs11_addattr(attrs + n++, CKA_ID, id, id_len);
342 
343 	/* Now call the pkcs11 module to create the object */
344 	rv = CRYPTOKI_call(ctx, C_CreateObject(spriv->session, attrs, n, &object));
345 
346 	/* Zap all memory allocated when building the template */
347 	pkcs11_zap_attrs(attrs, n);
348 
349 	CRYPTOKI_checkerr(CKR_F_PKCS11_STORE_CERTIFICATE, rv);
350 
351 	/* Gobble the key object */
352 	return pkcs11_init_cert(ctx, token, spriv->session, object, ret_cert);
353 }
354 
355 /* vim: set noexpandtab: */
356