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