summaryrefslogtreecommitdiffstats
path: root/crypto/der.h
blob: 0e895bbeec2f1932487c9ca97d0320fd9fee3e44 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
/*
 * Copyright (c) 2022 Bytedance
 * Author: lei he <helei.sig11@bytedance.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
 *
 */

#ifndef QCRYPTO_ASN1_DECODER_H
#define QCRYPTO_ASN1_DECODER_H

#include "qapi/error.h"

typedef struct QCryptoEncodeContext QCryptoEncodeContext;

/* rsaEncryption: 1.2.840.113549.1.1.1 */
#define QCRYPTO_OID_rsaEncryption "\x2A\x86\x48\x86\xF7\x0D\x01\x01\x01"

/* Simple decoder used to parse DER encoded rsa keys. */

/**
 *  @opaque: user context.
 *  @value: the starting address of |value| part of 'Tag-Length-Value' pattern.
 *  @vlen: length of the |value|.
 *  Returns: 0 for success, any other value is considered an error.
 */
typedef int (*QCryptoDERDecodeCb) (void *opaque, const uint8_t *value,
                                   size_t vlen, Error **errp);

/**
 * qcrypto_der_decode_int:
 * @data: pointer to address of input data
 * @dlen: pointer to length of input data
 * @cb: callback invoked when decode succeed, if cb equals NULL, no
 * callback will be invoked
 * @opaque: parameter passed to cb
 *
 * Decode integer from DER-encoded data.
 *
 * Returns: On success, *data points to rest data, and *dlen
 * will be set to the rest length of data, if cb is not NULL, must
 * return 0 to make decode success, at last, the length of the data
 * part of the decoded INTEGER will be returned. Otherwise, -1 is
 * returned and the valued of *data and *dlen keep unchanged.
 */
int qcrypto_der_decode_int(const uint8_t **data,
                           size_t *dlen,
                           QCryptoDERDecodeCb cb,
                           void *opaque,
                           Error **errp);
/**
 * qcrypto_der_decode_seq:
 *
 * Decode sequence from DER-encoded data, similar with der_decode_int.
 *
 * @data: pointer to address of input data
 * @dlen: pointer to length of input data
 * @cb: callback invoked when decode succeed, if cb equals NULL, no
 * callback will be invoked
 * @opaque: parameter passed to cb
 *
 * Returns: On success, *data points to rest data, and *dlen
 * will be set to the rest length of data, if cb is not NULL, must
 * return 0 to make decode success, at last, the length of the data
 * part of the decoded SEQUENCE will be returned. Otherwise, -1 is
 * returned and the valued of *data and *dlen keep unchanged.
 */
int qcrypto_der_decode_seq(const uint8_t **data,
                           size_t *dlen,
                           QCryptoDERDecodeCb cb,
                           void *opaque,
                           Error **errp);

/**
 * qcrypto_der_decode_oid:
 *
 * Decode OID from DER-encoded data, similar with der_decode_int.
 *
 * @data: pointer to address of input data
 * @dlen: pointer to length of input data
 * @cb: callback invoked when decode succeed, if cb equals NULL, no
 * callback will be invoked
 * @opaque: parameter passed to cb
 *
 * Returns: On success, *data points to rest data, and *dlen
 * will be set to the rest length of data, if cb is not NULL, must
 * return 0 to make decode success, at last, the length of the data
 * part of the decoded OID will be returned. Otherwise, -1 is
 * returned and the valued of *data and *dlen keep unchanged.
 */
int qcrypto_der_decode_oid(const uint8_t **data,
                           size_t *dlen,
                           QCryptoDERDecodeCb cb,
                           void *opaque,
                           Error **errp);

/**
 * qcrypto_der_decode_octet_str:
 *
 * Decode OCTET STRING from DER-encoded data, similar with der_decode_int.
 *
 * @data: pointer to address of input data
 * @dlen: pointer to length of input data
 * @cb: callback invoked when decode succeed, if cb equals NULL, no
 * callback will be invoked
 * @opaque: parameter passed to cb
 *
 * Returns: On success, *data points to rest data, and *dlen
 * will be set to the rest length of data, if cb is not NULL, must
 * return 0 to make decode success, at last, the length of the data
 * part of the decoded OCTET STRING will be returned. Otherwise, -1 is
 * returned and the valued of *data and *dlen keep unchanged.
 */
int qcrypto_der_decode_octet_str(const uint8_t **data,
                                 size_t *dlen,
                                 QCryptoDERDecodeCb cb,
                                 void *opaque,
                                 Error **errp);

/**
 * qcrypto_der_decode_bit_str:
 *
 * Decode BIT STRING from DER-encoded data, similar with der_decode_int.
 *
 * @data: pointer to address of input data
 * @dlen: pointer to length of input data
 * @cb: callback invoked when decode succeed, if cb equals NULL, no
 * callback will be invoked
 * @opaque: parameter passed to cb
 *
 * Returns: On success, *data points to rest data, and *dlen
 * will be set to the rest length of data, if cb is not NULL, must
 * return 0 to make decode success, at last, the length of the data
 * part of the decoded BIT STRING will be returned. Otherwise, -1 is
 * returned and the valued of *data and *dlen keep unchanged.
 */
int qcrypto_der_decode_bit_str(const uint8_t **data,
                               size_t *dlen,
                               QCryptoDERDecodeCb cb,
                               void *opaque,
                               Error **errp);


/**
 * qcrypto_der_decode_ctx_tag:
 *
 * Decode context specific tag
 *
 * @data: pointer to address of input data
 * @dlen: pointer to length of input data
 * @tag: expected value of context specific tag
 * @cb: callback invoked when decode succeed, if cb equals NULL, no
 * callback will be invoked
 * @opaque: parameter passed to cb
 *
 * Returns: On success, *data points to rest data, and *dlen
 * will be set to the rest length of data, if cb is not NULL, must
 * return 0 to make decode success, at last, the length of the data
 * part of the decoded BIT STRING will be returned. Otherwise, -1 is
 * returned and the valued of *data and *dlen keep unchanged.
 */
int qcrypto_der_decode_ctx_tag(const uint8_t **data,
                               size_t *dlen, int tag_id,
                               QCryptoDERDecodeCb cb,
                               void *opaque,
                               Error **errp);

/**
 * qcrypto_der_encode_ctx_new:
 *
 * Allocate a context used for der encoding.
 */
QCryptoEncodeContext *qcrypto_der_encode_ctx_new(void);

/**
 * qcrypto_der_encode_seq_begin:
 * @ctx: the encode context.
 *
 * Start encoding a SEQUENCE for ctx.
 *
 */
void qcrypto_der_encode_seq_begin(QCryptoEncodeContext *ctx);

/**
 * qcrypto_der_encode_seq_begin:
 * @ctx: the encode context.
 *
 * Finish uencoding a SEQUENCE for ctx.
 *
 */
void qcrypto_der_encode_seq_end(QCryptoEncodeContext *ctx);


/**
 * qcrypto_der_encode_oid:
 * @ctx: the encode context.
 * @src: the source data of oid, note it should be already encoded, this
 * function only add tag and length part for it.
 *
 * Encode an oid into ctx.
 */
void qcrypto_der_encode_oid(QCryptoEncodeContext *ctx,
                            const uint8_t *src, size_t src_len);

/**
 * qcrypto_der_encode_int:
 * @ctx: the encode context.
 * @src: the source data of integer, note it should be already encoded, this
 * function only add tag and length part for it.
 *
 * Encode an integer into ctx.
 */
void qcrypto_der_encode_int(QCryptoEncodeContext *ctx,
                            const uint8_t *src, size_t src_len);

/**
 * qcrypto_der_encode_null:
 * @ctx: the encode context.
 *
 * Encode a null into ctx.
 */
void qcrypto_der_encode_null(QCryptoEncodeContext *ctx);

/**
 * qcrypto_der_encode_octet_str:
 * @ctx: the encode context.
 * @src: the source data of the octet string.
 *
 * Encode a octet string into ctx.
 */
void qcrypto_der_encode_octet_str(QCryptoEncodeContext *ctx,
                                  const uint8_t *src, size_t src_len);

/**
 * qcrypto_der_encode_octet_str_begin:
 * @ctx: the encode context.
 *
 * Start encoding a octet string, All fields between
 * qcrypto_der_encode_octet_str_begin and qcrypto_der_encode_octet_str_end
 * are encoded as an octet string. This is useful when we need to encode a
 * encoded SEQUNCE as OCTET STRING.
 */
void qcrypto_der_encode_octet_str_begin(QCryptoEncodeContext *ctx);

/**
 * qcrypto_der_encode_octet_str_end:
 * @ctx: the encode context.
 *
 * Finish encoding a octet string, All fields between
 * qcrypto_der_encode_octet_str_begin and qcrypto_der_encode_octet_str_end
 * are encoded as an octet string. This is useful when we need to encode a
 * encoded SEQUNCE as OCTET STRING.
 */
void qcrypto_der_encode_octet_str_end(QCryptoEncodeContext *ctx);

/**
 * qcrypto_der_encode_ctx_buffer_len:
 * @ctx: the encode context.
 *
 * Compute the expected buffer size to save all encoded things.
 */
size_t qcrypto_der_encode_ctx_buffer_len(QCryptoEncodeContext *ctx);

/**
 * qcrypto_der_encode_ctx_flush_and_free:
 * @ctx: the encode context.
 * @dst: the distination to save the encoded data, the length of dst should
 * not less than qcrypto_der_encode_cxt_buffer_len
 *
 * Flush all encoded data into dst, then free ctx.
 */
void qcrypto_der_encode_ctx_flush_and_free(QCryptoEncodeContext *ctx,
                                           uint8_t *dst);

#endif  /* QCRYPTO_ASN1_DECODER_H */