xref: /netbsd-src/external/bsd/libfido2/dist/src/blob.c (revision 2d40c4512a84c0d064ec30a492c5e2a14d230bc3)
1ba9bdd8bSchristos /*
2ba9bdd8bSchristos  * Copyright (c) 2018 Yubico AB. All rights reserved.
3ba9bdd8bSchristos  * Use of this source code is governed by a BSD-style
4ba9bdd8bSchristos  * license that can be found in the LICENSE file.
5*2d40c451Schristos  * SPDX-License-Identifier: BSD-2-Clause
6ba9bdd8bSchristos  */
7ba9bdd8bSchristos 
8ba9bdd8bSchristos #include "fido.h"
9ba9bdd8bSchristos 
10ba9bdd8bSchristos fido_blob_t *
fido_blob_new(void)11ba9bdd8bSchristos fido_blob_new(void)
12ba9bdd8bSchristos {
1395dbdf32Schristos 	return calloc(1, sizeof(fido_blob_t));
1495dbdf32Schristos }
1595dbdf32Schristos 
1695dbdf32Schristos void
fido_blob_reset(fido_blob_t * b)1795dbdf32Schristos fido_blob_reset(fido_blob_t *b)
1895dbdf32Schristos {
1995dbdf32Schristos 	freezero(b->ptr, b->len);
2095dbdf32Schristos 	explicit_bzero(b, sizeof(*b));
21ba9bdd8bSchristos }
22ba9bdd8bSchristos 
23ba9bdd8bSchristos int
fido_blob_set(fido_blob_t * b,const u_char * ptr,size_t len)2495dbdf32Schristos fido_blob_set(fido_blob_t *b, const u_char *ptr, size_t len)
25ba9bdd8bSchristos {
2695dbdf32Schristos 	fido_blob_reset(b);
27ba9bdd8bSchristos 
28ba9bdd8bSchristos 	if (ptr == NULL || len == 0) {
29ba9bdd8bSchristos 		fido_log_debug("%s: ptr=%p, len=%zu", __func__,
30ba9bdd8bSchristos 		    (const void *)ptr, len);
3195dbdf32Schristos 		return -1;
32ba9bdd8bSchristos 	}
33ba9bdd8bSchristos 
34ba9bdd8bSchristos 	if ((b->ptr = malloc(len)) == NULL) {
35ba9bdd8bSchristos 		fido_log_debug("%s: malloc", __func__);
3695dbdf32Schristos 		return -1;
37ba9bdd8bSchristos 	}
38ba9bdd8bSchristos 
39ba9bdd8bSchristos 	memcpy(b->ptr, ptr, len);
40ba9bdd8bSchristos 	b->len = len;
41ba9bdd8bSchristos 
4295dbdf32Schristos 	return 0;
4395dbdf32Schristos }
4495dbdf32Schristos 
4595dbdf32Schristos int
fido_blob_append(fido_blob_t * b,const u_char * ptr,size_t len)4695dbdf32Schristos fido_blob_append(fido_blob_t *b, const u_char *ptr, size_t len)
4795dbdf32Schristos {
4895dbdf32Schristos 	u_char *tmp;
4995dbdf32Schristos 
5095dbdf32Schristos 	if (ptr == NULL || len == 0) {
5195dbdf32Schristos 		fido_log_debug("%s: ptr=%p, len=%zu", __func__,
5295dbdf32Schristos 		    (const void *)ptr, len);
5395dbdf32Schristos 		return -1;
5495dbdf32Schristos 	}
5595dbdf32Schristos 	if (SIZE_MAX - b->len < len) {
5695dbdf32Schristos 		fido_log_debug("%s: overflow", __func__);
5795dbdf32Schristos 		return -1;
5895dbdf32Schristos 	}
5995dbdf32Schristos 	if ((tmp = realloc(b->ptr, b->len + len)) == NULL) {
6095dbdf32Schristos 		fido_log_debug("%s: realloc", __func__);
6195dbdf32Schristos 		return -1;
6295dbdf32Schristos 	}
6395dbdf32Schristos 	b->ptr = tmp;
6495dbdf32Schristos 	memcpy(&b->ptr[b->len], ptr, len);
6595dbdf32Schristos 	b->len += len;
6695dbdf32Schristos 
6795dbdf32Schristos 	return 0;
68ba9bdd8bSchristos }
69ba9bdd8bSchristos 
70ba9bdd8bSchristos void
fido_blob_free(fido_blob_t ** bp)71ba9bdd8bSchristos fido_blob_free(fido_blob_t **bp)
72ba9bdd8bSchristos {
73ba9bdd8bSchristos 	fido_blob_t *b;
74ba9bdd8bSchristos 
75ba9bdd8bSchristos 	if (bp == NULL || (b = *bp) == NULL)
76ba9bdd8bSchristos 		return;
77ba9bdd8bSchristos 
7895dbdf32Schristos 	fido_blob_reset(b);
79ba9bdd8bSchristos 	free(b);
80ba9bdd8bSchristos 	*bp = NULL;
81ba9bdd8bSchristos }
82ba9bdd8bSchristos 
83ba9bdd8bSchristos void
fido_free_blob_array(fido_blob_array_t * array)84ba9bdd8bSchristos fido_free_blob_array(fido_blob_array_t *array)
85ba9bdd8bSchristos {
86ba9bdd8bSchristos 	if (array->ptr == NULL)
87ba9bdd8bSchristos 		return;
88ba9bdd8bSchristos 
89ba9bdd8bSchristos 	for (size_t i = 0; i < array->len; i++) {
90ba9bdd8bSchristos 		fido_blob_t *b = &array->ptr[i];
9195dbdf32Schristos 		freezero(b->ptr, b->len);
92ba9bdd8bSchristos 		b->ptr = NULL;
93ba9bdd8bSchristos 	}
94ba9bdd8bSchristos 
95ba9bdd8bSchristos 	free(array->ptr);
96ba9bdd8bSchristos 	array->ptr = NULL;
97ba9bdd8bSchristos 	array->len = 0;
98ba9bdd8bSchristos }
99ba9bdd8bSchristos 
100ba9bdd8bSchristos cbor_item_t *
fido_blob_encode(const fido_blob_t * b)101ba9bdd8bSchristos fido_blob_encode(const fido_blob_t *b)
102ba9bdd8bSchristos {
103ba9bdd8bSchristos 	if (b == NULL || b->ptr == NULL)
10495dbdf32Schristos 		return NULL;
105ba9bdd8bSchristos 
10695dbdf32Schristos 	return cbor_build_bytestring(b->ptr, b->len);
107ba9bdd8bSchristos }
108ba9bdd8bSchristos 
109ba9bdd8bSchristos int
fido_blob_decode(const cbor_item_t * item,fido_blob_t * b)110ba9bdd8bSchristos fido_blob_decode(const cbor_item_t *item, fido_blob_t *b)
111ba9bdd8bSchristos {
11295dbdf32Schristos 	return cbor_bytestring_copy(item, &b->ptr, &b->len);
113ba9bdd8bSchristos }
114ba9bdd8bSchristos 
115ba9bdd8bSchristos int
fido_blob_is_empty(const fido_blob_t * b)116ba9bdd8bSchristos fido_blob_is_empty(const fido_blob_t *b)
117ba9bdd8bSchristos {
11895dbdf32Schristos 	return b->ptr == NULL || b->len == 0;
11995dbdf32Schristos }
12095dbdf32Schristos 
12195dbdf32Schristos int
fido_blob_serialise(fido_blob_t * b,const cbor_item_t * item)12295dbdf32Schristos fido_blob_serialise(fido_blob_t *b, const cbor_item_t *item)
12395dbdf32Schristos {
12495dbdf32Schristos 	size_t alloc;
12595dbdf32Schristos 
12695dbdf32Schristos 	if (!fido_blob_is_empty(b))
12795dbdf32Schristos 		return -1;
12895dbdf32Schristos 	if ((b->len = cbor_serialize_alloc(item, &b->ptr, &alloc)) == 0) {
12995dbdf32Schristos 		b->ptr = NULL;
13095dbdf32Schristos 		return -1;
13195dbdf32Schristos 	}
13295dbdf32Schristos 
13395dbdf32Schristos 	return 0;
134ba9bdd8bSchristos }
135