xref: /freebsd/contrib/libfido2/src/blob.c (revision 4b9d6057)
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  * SPDX-License-Identifier: BSD-2-Clause
6  */
7 
8 #include "fido.h"
9 
10 fido_blob_t *
11 fido_blob_new(void)
12 {
13 	return calloc(1, sizeof(fido_blob_t));
14 }
15 
16 void
17 fido_blob_reset(fido_blob_t *b)
18 {
19 	freezero(b->ptr, b->len);
20 	explicit_bzero(b, sizeof(*b));
21 }
22 
23 int
24 fido_blob_set(fido_blob_t *b, const u_char *ptr, size_t len)
25 {
26 	fido_blob_reset(b);
27 
28 	if (ptr == NULL || len == 0) {
29 		fido_log_debug("%s: ptr=%p, len=%zu", __func__,
30 		    (const void *)ptr, len);
31 		return -1;
32 	}
33 
34 	if ((b->ptr = malloc(len)) == NULL) {
35 		fido_log_debug("%s: malloc", __func__);
36 		return -1;
37 	}
38 
39 	memcpy(b->ptr, ptr, len);
40 	b->len = len;
41 
42 	return 0;
43 }
44 
45 int
46 fido_blob_append(fido_blob_t *b, const u_char *ptr, size_t len)
47 {
48 	u_char *tmp;
49 
50 	if (ptr == NULL || len == 0) {
51 		fido_log_debug("%s: ptr=%p, len=%zu", __func__,
52 		    (const void *)ptr, len);
53 		return -1;
54 	}
55 	if (SIZE_MAX - b->len < len) {
56 		fido_log_debug("%s: overflow", __func__);
57 		return -1;
58 	}
59 	if ((tmp = realloc(b->ptr, b->len + len)) == NULL) {
60 		fido_log_debug("%s: realloc", __func__);
61 		return -1;
62 	}
63 	b->ptr = tmp;
64 	memcpy(&b->ptr[b->len], ptr, len);
65 	b->len += len;
66 
67 	return 0;
68 }
69 
70 void
71 fido_blob_free(fido_blob_t **bp)
72 {
73 	fido_blob_t *b;
74 
75 	if (bp == NULL || (b = *bp) == NULL)
76 		return;
77 
78 	fido_blob_reset(b);
79 	free(b);
80 	*bp = NULL;
81 }
82 
83 void
84 fido_free_blob_array(fido_blob_array_t *array)
85 {
86 	if (array->ptr == NULL)
87 		return;
88 
89 	for (size_t i = 0; i < array->len; i++) {
90 		fido_blob_t *b = &array->ptr[i];
91 		freezero(b->ptr, b->len);
92 		b->ptr = NULL;
93 	}
94 
95 	free(array->ptr);
96 	array->ptr = NULL;
97 	array->len = 0;
98 }
99 
100 cbor_item_t *
101 fido_blob_encode(const fido_blob_t *b)
102 {
103 	if (b == NULL || b->ptr == NULL)
104 		return NULL;
105 
106 	return cbor_build_bytestring(b->ptr, b->len);
107 }
108 
109 int
110 fido_blob_decode(const cbor_item_t *item, fido_blob_t *b)
111 {
112 	return cbor_bytestring_copy(item, &b->ptr, &b->len);
113 }
114 
115 int
116 fido_blob_is_empty(const fido_blob_t *b)
117 {
118 	return b->ptr == NULL || b->len == 0;
119 }
120 
121 int
122 fido_blob_serialise(fido_blob_t *b, const cbor_item_t *item)
123 {
124 	size_t alloc;
125 
126 	if (!fido_blob_is_empty(b))
127 		return -1;
128 	if ((b->len = cbor_serialize_alloc(item, &b->ptr, &alloc)) == 0) {
129 		b->ptr = NULL;
130 		return -1;
131 	}
132 
133 	return 0;
134 }
135