xref: /openbsd/lib/libfido2/src/iso7816.c (revision 097a140d)
1 /*
2  * Copyright (c) 2018 Yubico AB. All rights reserved.
3  * Use of this source code is governed by a BSD-style
4  * license that can be found in the LICENSE file.
5  */
6 
7 #include <string.h>
8 #include "fido.h"
9 
10 iso7816_apdu_t *
11 iso7816_new(uint8_t ins, uint8_t p1, uint16_t payload_len)
12 {
13 	iso7816_apdu_t	*apdu;
14 	size_t		 alloc_len;
15 
16 	alloc_len = sizeof(iso7816_apdu_t) + payload_len + 2; /* le1 le2 */
17 
18 	if ((apdu = calloc(1, alloc_len)) == NULL)
19 		return (NULL);
20 
21 	apdu->alloc_len = alloc_len;
22 	apdu->payload_len = payload_len;
23 	apdu->payload_ptr = apdu->payload;
24 	apdu->header.ins = ins;
25 	apdu->header.p1 = p1;
26 	apdu->header.lc2 = (uint8_t)((payload_len >> 8) & 0xff);
27 	apdu->header.lc3 = (uint8_t)(payload_len & 0xff);
28 
29 	return (apdu);
30 }
31 
32 void
33 iso7816_free(iso7816_apdu_t **apdu_p)
34 {
35 	iso7816_apdu_t *apdu;
36 
37 	if (apdu_p == NULL || (apdu = *apdu_p) == NULL)
38 		return;
39 
40 	explicit_bzero(apdu, apdu->alloc_len);
41 	free(apdu);
42 
43 	*apdu_p = NULL;
44 }
45 
46 int
47 iso7816_add(iso7816_apdu_t *apdu, const void *buf, size_t cnt)
48 {
49 	if (cnt > apdu->payload_len || cnt > UINT16_MAX)
50 		return (-1);
51 
52 	memcpy(apdu->payload_ptr, buf, cnt);
53 	apdu->payload_ptr += cnt;
54 	apdu->payload_len = (uint16_t)(apdu->payload_len - cnt);
55 
56 	return (0);
57 }
58 
59 const unsigned char *
60 iso7816_ptr(const iso7816_apdu_t *apdu)
61 {
62 	return ((const unsigned char *)&apdu->header);
63 }
64 
65 size_t
66 iso7816_len(const iso7816_apdu_t *apdu)
67 {
68 	return (apdu->alloc_len - sizeof(apdu->alloc_len) -
69 	    sizeof(apdu->payload_len) - sizeof(apdu->payload_ptr));
70 }
71