1 /*
2  * Copyright (c) 2005-2018 Alon Bar-Lev <alon.barlev@gmail.com>
3  *
4  * This software is available to you under a choice of one of two
5  * licenses.  You may choose to be licensed under the terms of the GNU
6  * General Public License (GPL) Version 2, or the BSD license.
7  *
8  * GNU General Public License (GPL) Version 2
9  * ===========================================
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License version 2
12  * as published by the Free Software Foundation.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program (see the file COPYING.GPL included with this
21  * distribution); if not, write to the Free Software Foundation, Inc.,
22  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23  *
24  * BSD License
25  * ============
26  * Redistribution and use in source and binary forms, with or without
27  * modification, are permitted provided that the following conditions are met:
28  *
29  *     o Redistributions of source code must retain the above copyright notice,
30  *       this list of conditions and the following disclaimer.
31  *     o Redistributions in binary form must reproduce the above copyright
32  *       notice, this list of conditions and the following disclaimer in the
33  *       documentation and/or other materials provided with the distribution.
34  *     o Neither the name of the Alon Bar-Lev nor the names of its
35  *       contributors may be used to endorse or promote products derived from
36  *       this software without specific prior written permission.
37  *
38  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
39  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
40  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
41  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
42  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
43  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
44  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
45  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
46  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
47  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
48  * POSSIBILITY OF SUCH DAMAGE.
49  */
50 
51 #include "common.h"
52 
53 #include "_pkcs11h-core.h"
54 #include "_pkcs11h-mem.h"
55 #include "_pkcs11h-util.h"
56 #include "_pkcs11h-token.h"
57 #include "_pkcs11h-certificate.h"
58 
59 #define __PKCS11H_SERIALIZE_INVALID_CHARS	"\\/\"'%&#@!?$* <>{}[]()`|:;,.+-"
60 
61 #if defined(ENABLE_PKCS11H_TOKEN) || defined(ENABLE_PKCS11H_CERTIFICATE)
62 
63 CK_RV
pkcs11h_token_serializeTokenId(OUT char * const sz,IN OUT size_t * max,IN const pkcs11h_token_id_t token_id)64 pkcs11h_token_serializeTokenId (
65 	OUT char * const sz,
66 	IN OUT size_t *max,
67 	IN const pkcs11h_token_id_t token_id
68 ) {
69 	const char *sources[5];
70 	CK_RV rv = CKR_FUNCTION_FAILED;
71 	size_t n;
72 	int e;
73 
74 	/*_PKCS11H_ASSERT (sz!=NULL); Not required*/
75 	_PKCS11H_ASSERT (max!=NULL);
76 	_PKCS11H_ASSERT (token_id!=NULL);
77 
78 	{ /* Must be after assert */
79 		sources[0] = token_id->manufacturerID;
80 		sources[1] = token_id->model;
81 		sources[2] = token_id->serialNumber;
82 		sources[3] = token_id->label;
83 		sources[4] = NULL;
84 	}
85 
86 	_PKCS11H_DEBUG (
87 		PKCS11H_LOG_DEBUG2,
88 		"PKCS#11: pkcs11h_token_serializeTokenId entry sz=%p, *max="P_Z", token_id=%p",
89 		sz,
90 		sz != NULL ? *max : 0,
91 		(void *)token_id
92 	);
93 
94 	n = 0;
95 	for (e=0;sources[e] != NULL;e++) {
96 		size_t t;
97 		if (
98 			(rv = _pkcs11h_util_escapeString (
99 				NULL,
100 				sources[e],
101 				&t,
102 				__PKCS11H_SERIALIZE_INVALID_CHARS
103 			)) != CKR_OK
104 		) {
105 			goto cleanup;
106 		}
107 		n+=t;
108 	}
109 
110 	if (sz != NULL) {
111 		if (*max < n) {
112 			rv = CKR_ATTRIBUTE_VALUE_INVALID;
113 			goto cleanup;
114 		}
115 
116 		n = 0;
117 		for (e=0;sources[e] != NULL;e++) {
118 			size_t t = *max-n;
119 			if (
120 				(rv = _pkcs11h_util_escapeString (
121 					sz+n,
122 					sources[e],
123 					&t,
124 					__PKCS11H_SERIALIZE_INVALID_CHARS
125 				)) != CKR_OK
126 			) {
127 				goto cleanup;
128 			}
129 			n+=t;
130 			sz[n-1] = '/';
131 		}
132 		sz[n-1] = '\x0';
133 	}
134 
135 	*max = n;
136 	rv = CKR_OK;
137 
138 cleanup:
139 
140 	_PKCS11H_DEBUG (
141 		PKCS11H_LOG_DEBUG2,
142 		"PKCS#11: pkcs11h_token_serializeTokenId return rv=%lu-'%s', *max="P_Z", sz='%s'",
143 		rv,
144 		pkcs11h_getMessage (rv),
145 		*max,
146 		sz
147 	);
148 
149 	return rv;
150 }
151 
152 CK_RV
pkcs11h_token_deserializeTokenId(OUT pkcs11h_token_id_t * p_token_id,IN const char * const sz)153 pkcs11h_token_deserializeTokenId (
154 	OUT pkcs11h_token_id_t *p_token_id,
155 	IN const char * const sz
156 ) {
157 #define __PKCS11H_TARGETS_NUMBER 4
158 	struct {
159 		char *p;
160 		size_t s;
161 	} targets[__PKCS11H_TARGETS_NUMBER];
162 
163 	pkcs11h_token_id_t token_id = NULL;
164 	char *p1 = NULL;
165 	char *_sz = NULL;
166 	int e;
167 	CK_RV rv = CKR_FUNCTION_FAILED;
168 
169 	_PKCS11H_ASSERT (p_token_id!=NULL);
170 	_PKCS11H_ASSERT (sz!=NULL);
171 
172 	_PKCS11H_DEBUG (
173 		PKCS11H_LOG_DEBUG2,
174 		"PKCS#11: pkcs11h_token_deserializeTokenId entry p_token_id=%p, sz='%s'",
175 		(void *)p_token_id,
176 		sz
177 	);
178 
179 	*p_token_id = NULL;
180 
181 	if (
182 		(rv = _pkcs11h_mem_strdup (
183 			(void *)&_sz,
184 			sz
185 		)) != CKR_OK
186 	) {
187 		goto cleanup;
188 	}
189 
190 	p1 = _sz;
191 
192 	if ((rv = _pkcs11h_token_newTokenId (&token_id)) != CKR_OK) {
193 		goto cleanup;
194 	}
195 
196 	targets[0].p = token_id->manufacturerID;
197 	targets[0].s = sizeof (token_id->manufacturerID);
198 	targets[1].p = token_id->model;
199 	targets[1].s = sizeof (token_id->model);
200 	targets[2].p = token_id->serialNumber;
201 	targets[2].s = sizeof (token_id->serialNumber);
202 	targets[3].p = token_id->label;
203 	targets[3].s = sizeof (token_id->label);
204 
205 	for (e=0;e < __PKCS11H_TARGETS_NUMBER;e++) {
206 		size_t l;
207 		char *p2 = NULL;
208 
209 		/*
210 		 * Don't search for last
211 		 * separator
212 		 */
213 		if (e != __PKCS11H_TARGETS_NUMBER-1) {
214 			p2 = strchr (p1, '/');
215 			if (p2 == NULL) {
216 				rv = CKR_ATTRIBUTE_VALUE_INVALID;
217 				goto cleanup;
218 			}
219 			else {
220 				*p2 = '\x0';
221 			}
222 		}
223 
224 		if (
225 			(rv = _pkcs11h_util_unescapeString (
226 				NULL,
227 				p1,
228 				&l
229 			)) != CKR_OK
230 		) {
231 			goto cleanup;
232 		}
233 
234 		if (l > targets[e].s) {
235 			rv = CKR_ATTRIBUTE_VALUE_INVALID;
236 			goto cleanup;
237 		}
238 
239 		l = targets[e].s;
240 
241 		if (
242 			(rv = _pkcs11h_util_unescapeString (
243 				targets[e].p,
244 				p1,
245 				&l
246 			)) != CKR_OK
247 		) {
248 			goto cleanup;
249 		}
250 
251 		p1 = p2+1;
252 	}
253 
254 	strncpy (
255 		token_id->display,
256 		token_id->label,
257 		sizeof (token_id->display)
258 	);
259 
260 	*p_token_id = token_id;
261 	token_id = NULL;
262 
263 	rv = CKR_OK;
264 
265 cleanup:
266 
267 	if (_sz != NULL) {
268 		_pkcs11h_mem_free ((void *)&_sz);
269 	}
270 
271 	if (token_id != NULL) {
272 		pkcs11h_token_freeTokenId (token_id);
273 	}
274 
275 	_PKCS11H_DEBUG (
276 		PKCS11H_LOG_DEBUG2,
277 		"PKCS#11: pkcs11h_token_deserializeTokenId return rv=%lu-'%s'",
278 		rv,
279 		pkcs11h_getMessage (rv)
280 	);
281 
282 	return rv;
283 #undef __PKCS11H_TARGETS_NUMBER
284 }
285 
286 #endif				/* ENABLE_PKCS11H_TOKEN || ENABLE_PKCS11H_CERTIFICATE */
287 
288 #if defined(ENABLE_PKCS11H_CERTIFICATE)
289 
290 CK_RV
pkcs11h_certificate_serializeCertificateId(OUT char * const sz,IN OUT size_t * max,IN const pkcs11h_certificate_id_t certificate_id)291 pkcs11h_certificate_serializeCertificateId (
292 	OUT char * const sz,
293 	IN OUT size_t *max,
294 	IN const pkcs11h_certificate_id_t certificate_id
295 ) {
296 	CK_RV rv = CKR_FUNCTION_FAILED;
297 	size_t saved_max = 0;
298 	size_t n = 0;
299 	size_t _max = 0;
300 
301 	/*_PKCS11H_ASSERT (sz!=NULL); Not required */
302 	_PKCS11H_ASSERT (max!=NULL);
303 	_PKCS11H_ASSERT (certificate_id!=NULL);
304 
305 	_PKCS11H_DEBUG (
306 		PKCS11H_LOG_DEBUG2,
307 		"PKCS#11: pkcs11h_certificate_serializeCertificateId entry sz=%p, *max="P_Z", certificate_id=%p",
308 		sz,
309 		sz != NULL ? *max : 0,
310 		(void *)certificate_id
311 	);
312 
313 	if (sz != NULL) {
314 		saved_max = n = *max;
315 	}
316 	*max = 0;
317 
318 	if (
319 		(rv = pkcs11h_token_serializeTokenId (
320 			sz,
321 			&n,
322 			certificate_id->token_id
323 		)) != CKR_OK
324 	) {
325 		goto cleanup;
326 	}
327 
328 	_max = n + certificate_id->attrCKA_ID_size*2 + 1;
329 
330 	if (sz != NULL) {
331 		if (saved_max < _max) {
332 			rv = CKR_ATTRIBUTE_VALUE_INVALID;
333 			goto cleanup;
334 		}
335 
336 		sz[n-1] = '/';
337 		rv = _pkcs11h_util_binaryToHex (
338 			sz+n,
339 			saved_max-n,
340 			certificate_id->attrCKA_ID,
341 			certificate_id->attrCKA_ID_size
342 		);
343 	}
344 
345 	*max = _max;
346 	rv = CKR_OK;
347 
348 cleanup:
349 
350 	_PKCS11H_DEBUG (
351 		PKCS11H_LOG_DEBUG2,
352 		"PKCS#11: pkcs11h_certificate_serializeCertificateId return rv=%lu-'%s', *max="P_Z", sz='%s'",
353 		rv,
354 		pkcs11h_getMessage (rv),
355 		*max,
356 		sz
357 	);
358 
359 	return rv;
360 }
361 
362 CK_RV
pkcs11h_certificate_deserializeCertificateId(OUT pkcs11h_certificate_id_t * const p_certificate_id,IN const char * const sz)363 pkcs11h_certificate_deserializeCertificateId (
364 	OUT pkcs11h_certificate_id_t * const p_certificate_id,
365 	IN const char * const sz
366 ) {
367 	pkcs11h_certificate_id_t certificate_id = NULL;
368 	CK_RV rv = CKR_FUNCTION_FAILED;
369 	char *p = NULL;
370 	char *_sz = NULL;
371 
372 	_PKCS11H_ASSERT (p_certificate_id!=NULL);
373 	_PKCS11H_ASSERT (sz!=NULL);
374 
375 	*p_certificate_id = NULL;
376 
377 	_PKCS11H_DEBUG (
378 		PKCS11H_LOG_DEBUG2,
379 		"PKCS#11: pkcs11h_certificate_deserializeCertificateId entry p_certificate_id=%p, sz='%s'",
380 		(void *)p_certificate_id,
381 		sz
382 	);
383 
384 	if (
385 		(rv = _pkcs11h_mem_strdup (
386 			(void *)&_sz,
387 			sz
388 		)) != CKR_OK
389 	) {
390 		goto cleanup;
391 	}
392 
393 	p = _sz;
394 
395 	if ((rv = _pkcs11h_certificate_newCertificateId (&certificate_id)) != CKR_OK) {
396 		goto cleanup;
397 	}
398 
399 	if ((p = strrchr (_sz, '/')) == NULL) {
400 		rv = CKR_ATTRIBUTE_VALUE_INVALID;
401 		goto cleanup;
402 	}
403 
404 	*p = '\x0';
405 	p++;
406 
407 	if (
408 		(rv = pkcs11h_token_deserializeTokenId (
409 			&certificate_id->token_id,
410 			_sz
411 		)) != CKR_OK
412 	) {
413 		goto cleanup;
414 	}
415 
416 	certificate_id->attrCKA_ID_size = strlen (p)/2;
417 
418 	if (
419 		(rv = _pkcs11h_mem_malloc (
420 			(void *)&certificate_id->attrCKA_ID,
421 			certificate_id->attrCKA_ID_size)
422 		) != CKR_OK ||
423 		(rv = _pkcs11h_util_hexToBinary (
424 			certificate_id->attrCKA_ID,
425 			p,
426 			&certificate_id->attrCKA_ID_size
427 		)) != CKR_OK
428 	) {
429 		goto cleanup;
430 	}
431 
432 	*p_certificate_id = certificate_id;
433 	certificate_id = NULL;
434 	rv = CKR_OK;
435 
436 cleanup:
437 
438 	if (certificate_id != NULL) {
439 		pkcs11h_certificate_freeCertificateId (certificate_id);
440 		certificate_id = NULL;
441 	}
442 
443 	if (_sz != NULL) {
444 		_pkcs11h_mem_free ((void *)&_sz);
445 	}
446 
447 	_PKCS11H_DEBUG (
448 		PKCS11H_LOG_DEBUG2,
449 		"PKCS#11: pkcs11h_certificate_deserializeCertificateId return rv=%lu-'%s'",
450 		rv,
451 		pkcs11h_getMessage (rv)
452 	);
453 
454 	return rv;
455 
456 }
457 
458 #endif				/* ENABLE_PKCS11H_CERTIFICATE */
459 
460