Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/krb5/src/include/k5-der.h
34890 views
1
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
/* include/k5-der.h - Distinguished Encoding Rules (DER) declarations */
3
/*
4
* Copyright (C) 2023 by the Massachusetts Institute of Technology.
5
* All rights reserved.
6
*
7
* Redistribution and use in source and binary forms, with or without
8
* modification, are permitted provided that the following conditions
9
* are met:
10
*
11
* * Redistributions of source code must retain the above copyright
12
* notice, this list of conditions and the following disclaimer.
13
*
14
* * Redistributions in binary form must reproduce the above copyright
15
* notice, this list of conditions and the following disclaimer in
16
* the documentation and/or other materials provided with the
17
* distribution.
18
*
19
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
20
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
21
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
22
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
23
* COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
24
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
25
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
26
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
28
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
30
* OF THE POSSIBILITY OF SUCH DAMAGE.
31
*/
32
33
/*
34
* Most ASN.1 encoding and decoding is done using the table-driven framework in
35
* libkrb5. When that is not an option, these helpers can be used to encode
36
* and decode simple types.
37
*/
38
39
#ifndef K5_DER_H
40
#define K5_DER_H
41
42
#include <stdint.h>
43
#include <stdbool.h>
44
#include "k5-buf.h"
45
#include "k5-input.h"
46
47
/* Return the number of bytes needed to encode len as a DER encoding length. */
48
static inline size_t
49
k5_der_len_len(size_t len)
50
{
51
size_t llen;
52
53
if (len < 128)
54
return 1;
55
llen = 1;
56
while (len > 0) {
57
len >>= 8;
58
llen++;
59
}
60
return llen;
61
}
62
63
/* Return the number of bytes needed to encode a DER value (with identifier
64
* byte and length) for a given contents length. */
65
static inline size_t
66
k5_der_value_len(size_t contents_len)
67
{
68
return 1 + k5_der_len_len(contents_len) + contents_len;
69
}
70
71
/* Add a DER identifier byte (composed by the caller, including the ASN.1
72
* class, tag, and constructed bit) and length. */
73
static inline void
74
k5_der_add_taglen(struct k5buf *buf, uint8_t idbyte, size_t len)
75
{
76
uint8_t *p;
77
size_t llen = k5_der_len_len(len);
78
79
p = k5_buf_get_space(buf, 1 + llen);
80
if (p == NULL)
81
return;
82
*p++ = idbyte;
83
if (len < 128) {
84
*p = len;
85
} else {
86
*p = 0x80 | (llen - 1);
87
/* Encode the length bytes backwards so the most significant byte is
88
* first. */
89
p += llen;
90
while (len > 0) {
91
*--p = len & 0xFF;
92
len >>= 8;
93
}
94
}
95
}
96
97
/* Add a DER value (identifier byte, length, and contents). */
98
static inline void
99
k5_der_add_value(struct k5buf *buf, uint8_t idbyte, const void *contents,
100
size_t len)
101
{
102
k5_der_add_taglen(buf, idbyte, len);
103
k5_buf_add_len(buf, contents, len);
104
}
105
106
/*
107
* If the next byte in in matches idbyte and the subsequent DER length is
108
* valid, advance in past the tag and length, set *len_out to the decoded
109
* length, and return true. Otherwise return false. Only set an error on in
110
* if the next byte matches idbyte but the ensuing length is invalid.
111
*/
112
static inline bool
113
k5_der_get_taglen(struct k5input *in, uint8_t idbyte, size_t *len_out)
114
{
115
uint8_t lenbyte, i;
116
size_t len;
117
118
/* Do nothing if in is empty or the next byte doesn't match idbyte. */
119
if (in->status || in->len == 0 || *in->ptr != idbyte)
120
return false;
121
122
/* Advance past the identifier byte and decode the length. */
123
(void)k5_input_get_byte(in);
124
lenbyte = k5_input_get_byte(in);
125
if (lenbyte < 128) {
126
len = lenbyte;
127
} else {
128
len = 0;
129
for (i = 0; i < (lenbyte & 0x7F); i++) {
130
if (len > (SIZE_MAX >> 8)) {
131
k5_input_set_status(in, EOVERFLOW);
132
return false;
133
}
134
len = (len << 8) | k5_input_get_byte(in);
135
}
136
}
137
138
if (in->status)
139
return false;
140
141
*len_out = len;
142
return true;
143
}
144
145
/*
146
* If the next byte in in matches idbyte and the subsequent DER length is
147
* valid, advance in past the value, set *contents_out to the value contents,
148
* and return true. Otherwise return false. Only set an error on in if the
149
* next byte matches idbyte but the ensuing length is invalid. contents_out
150
* may be aliased to in; it will only be written to on successful decoding of a
151
* value.
152
*/
153
static inline bool
154
k5_der_get_value(struct k5input *in, uint8_t idbyte,
155
struct k5input *contents_out)
156
{
157
size_t len;
158
const void *bytes;
159
160
if (!k5_der_get_taglen(in, idbyte, &len))
161
return false;
162
bytes = k5_input_get_bytes(in, len);
163
if (bytes == NULL)
164
return false;
165
k5_input_init(contents_out, bytes, len);
166
return true;
167
}
168
169
#endif /* K5_DER_H */
170
171