xref: /freebsd-src/contrib/libfido2/src/iso7816.c (revision 2ccfa855b2fc331819953e3de1b1c15ce5b95a7e)
10afa8e06SEd Maste /*
20afa8e06SEd Maste  * Copyright (c) 2018 Yubico AB. All rights reserved.
30afa8e06SEd Maste  * Use of this source code is governed by a BSD-style
40afa8e06SEd Maste  * license that can be found in the LICENSE file.
5*2ccfa855SEd Maste  * SPDX-License-Identifier: BSD-2-Clause
60afa8e06SEd Maste  */
70afa8e06SEd Maste 
80afa8e06SEd Maste #include "fido.h"
90afa8e06SEd Maste 
100afa8e06SEd Maste iso7816_apdu_t *
iso7816_new(uint8_t cla,uint8_t ins,uint8_t p1,uint16_t payload_len)110afa8e06SEd Maste iso7816_new(uint8_t cla, uint8_t ins, uint8_t p1, uint16_t payload_len)
120afa8e06SEd Maste {
130afa8e06SEd Maste 	iso7816_apdu_t *apdu;
140afa8e06SEd Maste 	size_t alloc_len;
150afa8e06SEd Maste 
160afa8e06SEd Maste 	alloc_len = sizeof(iso7816_apdu_t) + payload_len + 2; /* le1 le2 */
170afa8e06SEd Maste 	if ((apdu = calloc(1, alloc_len)) == NULL)
180afa8e06SEd Maste 		return NULL;
190afa8e06SEd Maste 	apdu->alloc_len = alloc_len;
200afa8e06SEd Maste 	apdu->payload_len = payload_len;
210afa8e06SEd Maste 	apdu->payload_ptr = apdu->payload;
220afa8e06SEd Maste 	apdu->header.cla = cla;
230afa8e06SEd Maste 	apdu->header.ins = ins;
240afa8e06SEd Maste 	apdu->header.p1 = p1;
250afa8e06SEd Maste 	apdu->header.lc2 = (uint8_t)((payload_len >> 8) & 0xff);
260afa8e06SEd Maste 	apdu->header.lc3 = (uint8_t)(payload_len & 0xff);
270afa8e06SEd Maste 
280afa8e06SEd Maste 	return apdu;
290afa8e06SEd Maste }
300afa8e06SEd Maste 
310afa8e06SEd Maste void
iso7816_free(iso7816_apdu_t ** apdu_p)320afa8e06SEd Maste iso7816_free(iso7816_apdu_t **apdu_p)
330afa8e06SEd Maste {
340afa8e06SEd Maste 	iso7816_apdu_t *apdu;
350afa8e06SEd Maste 
360afa8e06SEd Maste 	if (apdu_p == NULL || (apdu = *apdu_p) == NULL)
370afa8e06SEd Maste 		return;
380afa8e06SEd Maste 	freezero(apdu, apdu->alloc_len);
390afa8e06SEd Maste 	*apdu_p = NULL;
400afa8e06SEd Maste }
410afa8e06SEd Maste 
420afa8e06SEd Maste int
iso7816_add(iso7816_apdu_t * apdu,const void * buf,size_t cnt)430afa8e06SEd Maste iso7816_add(iso7816_apdu_t *apdu, const void *buf, size_t cnt)
440afa8e06SEd Maste {
450afa8e06SEd Maste 	if (cnt > apdu->payload_len || cnt > UINT16_MAX)
460afa8e06SEd Maste 		return -1;
470afa8e06SEd Maste 	memcpy(apdu->payload_ptr, buf, cnt);
480afa8e06SEd Maste 	apdu->payload_ptr += cnt;
490afa8e06SEd Maste 	apdu->payload_len = (uint16_t)(apdu->payload_len - cnt);
500afa8e06SEd Maste 
510afa8e06SEd Maste 	return 0;
520afa8e06SEd Maste }
530afa8e06SEd Maste 
540afa8e06SEd Maste const unsigned char *
iso7816_ptr(const iso7816_apdu_t * apdu)550afa8e06SEd Maste iso7816_ptr(const iso7816_apdu_t *apdu)
560afa8e06SEd Maste {
570afa8e06SEd Maste 	return (const unsigned char *)&apdu->header;
580afa8e06SEd Maste }
590afa8e06SEd Maste 
600afa8e06SEd Maste size_t
iso7816_len(const iso7816_apdu_t * apdu)610afa8e06SEd Maste iso7816_len(const iso7816_apdu_t *apdu)
620afa8e06SEd Maste {
63224a95f1SJessica Clarke 	return apdu->alloc_len - offsetof(iso7816_apdu_t, header) -
64224a95f1SJessica Clarke 	    (sizeof(iso7816_apdu_t) - offsetof(iso7816_apdu_t, payload));
650afa8e06SEd Maste }
66