1 /**
2  * \file asn1write.h
3  *
4  * \brief ASN.1 buffer writing functionality
5  */
6 /*
7  *  Copyright The Mbed TLS Contributors
8  *  SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
9  */
10 #ifndef MBEDTLS_ASN1_WRITE_H
11 #define MBEDTLS_ASN1_WRITE_H
12 
13 #include "mbedtls/build_info.h"
14 
15 #include "mbedtls/asn1.h"
16 
17 #define MBEDTLS_ASN1_CHK_ADD(g, f)                      \
18     do                                                  \
19     {                                                   \
20         if ((ret = (f)) < 0)                         \
21         return ret;                              \
22         else                                            \
23         (g) += ret;                                 \
24     } while (0)
25 
26 #define MBEDTLS_ASN1_CHK_CLEANUP_ADD(g, f)                      \
27     do                                                  \
28     {                                                   \
29         if ((ret = (f)) < 0)                         \
30         goto cleanup;                              \
31         else                                            \
32         (g) += ret;                                 \
33     } while (0)
34 
35 #ifdef __cplusplus
36 extern "C" {
37 #endif
38 
39 #if defined(MBEDTLS_ASN1_WRITE_C) || defined(MBEDTLS_X509_USE_C) || \
40     defined(MBEDTLS_PSA_UTIL_HAVE_ECDSA)
41 /**
42  * \brief           Write a length field in ASN.1 format.
43  *
44  * \note            This function works backwards in data buffer.
45  *
46  * \param p         The reference to the current position pointer.
47  * \param start     The start of the buffer, for bounds-checking.
48  * \param len       The length value to write.
49  *
50  * \return          The number of bytes written to \p p on success.
51  * \return          A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
52  */
53 int mbedtls_asn1_write_len(unsigned char **p, const unsigned char *start,
54                            size_t len);
55 /**
56  * \brief           Write an ASN.1 tag in ASN.1 format.
57  *
58  * \note            This function works backwards in data buffer.
59  *
60  * \param p         The reference to the current position pointer.
61  * \param start     The start of the buffer, for bounds-checking.
62  * \param tag       The tag to write.
63  *
64  * \return          The number of bytes written to \p p on success.
65  * \return          A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
66  */
67 int mbedtls_asn1_write_tag(unsigned char **p, const unsigned char *start,
68                            unsigned char tag);
69 #endif /* MBEDTLS_ASN1_WRITE_C || MBEDTLS_X509_USE_C || MBEDTLS_PSA_UTIL_HAVE_ECDSA*/
70 
71 #if defined(MBEDTLS_ASN1_WRITE_C)
72 /**
73  * \brief           Write raw buffer data.
74  *
75  * \note            This function works backwards in data buffer.
76  *
77  * \param p         The reference to the current position pointer.
78  * \param start     The start of the buffer, for bounds-checking.
79  * \param buf       The data buffer to write.
80  * \param size      The length of the data buffer.
81  *
82  * \return          The number of bytes written to \p p on success.
83  * \return          A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
84  */
85 int mbedtls_asn1_write_raw_buffer(unsigned char **p, const unsigned char *start,
86                                   const unsigned char *buf, size_t size);
87 
88 #if defined(MBEDTLS_BIGNUM_C)
89 /**
90  * \brief           Write an arbitrary-precision number (#MBEDTLS_ASN1_INTEGER)
91  *                  in ASN.1 format.
92  *
93  * \note            This function works backwards in data buffer.
94  *
95  * \param p         The reference to the current position pointer.
96  * \param start     The start of the buffer, for bounds-checking.
97  * \param X         The MPI to write.
98  *                  It must be non-negative.
99  *
100  * \return          The number of bytes written to \p p on success.
101  * \return          A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
102  */
103 int mbedtls_asn1_write_mpi(unsigned char **p, const unsigned char *start,
104                            const mbedtls_mpi *X);
105 #endif /* MBEDTLS_BIGNUM_C */
106 
107 /**
108  * \brief           Write a NULL tag (#MBEDTLS_ASN1_NULL) with zero data
109  *                  in ASN.1 format.
110  *
111  * \note            This function works backwards in data buffer.
112  *
113  * \param p         The reference to the current position pointer.
114  * \param start     The start of the buffer, for bounds-checking.
115  *
116  * \return          The number of bytes written to \p p on success.
117  * \return          A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
118  */
119 int mbedtls_asn1_write_null(unsigned char **p, const unsigned char *start);
120 
121 /**
122  * \brief           Write an OID tag (#MBEDTLS_ASN1_OID) and data
123  *                  in ASN.1 format.
124  *
125  * \note            This function works backwards in data buffer.
126  *
127  * \param p         The reference to the current position pointer.
128  * \param start     The start of the buffer, for bounds-checking.
129  * \param oid       The OID to write.
130  * \param oid_len   The length of the OID.
131  *
132  * \return          The number of bytes written to \p p on success.
133  * \return          A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
134  */
135 int mbedtls_asn1_write_oid(unsigned char **p, const unsigned char *start,
136                            const char *oid, size_t oid_len);
137 
138 /**
139  * \brief           Write an AlgorithmIdentifier sequence in ASN.1 format.
140  *
141  * \note            This function works backwards in data buffer.
142  *
143  * \param p         The reference to the current position pointer.
144  * \param start     The start of the buffer, for bounds-checking.
145  * \param oid       The OID of the algorithm to write.
146  * \param oid_len   The length of the algorithm's OID.
147  * \param par_len   The length of the parameters, which must be already written.
148  *                  If 0, NULL parameters are added
149  *
150  * \return          The number of bytes written to \p p on success.
151  * \return          A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
152  */
153 int mbedtls_asn1_write_algorithm_identifier(unsigned char **p,
154                                             const unsigned char *start,
155                                             const char *oid, size_t oid_len,
156                                             size_t par_len);
157 
158 /**
159  * \brief           Write an AlgorithmIdentifier sequence in ASN.1 format.
160  *
161  * \note            This function works backwards in data buffer.
162  *
163  * \param p         The reference to the current position pointer.
164  * \param start     The start of the buffer, for bounds-checking.
165  * \param oid       The OID of the algorithm to write.
166  * \param oid_len   The length of the algorithm's OID.
167  * \param par_len   The length of the parameters, which must be already written.
168  * \param has_par   If there are any parameters. If 0, par_len must be 0. If 1
169  *                  and \p par_len is 0, NULL parameters are added.
170  *
171  * \return          The number of bytes written to \p p on success.
172  * \return          A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
173  */
174 int mbedtls_asn1_write_algorithm_identifier_ext(unsigned char **p,
175                                                 const unsigned char *start,
176                                                 const char *oid, size_t oid_len,
177                                                 size_t par_len, int has_par);
178 
179 /**
180  * \brief           Write a boolean tag (#MBEDTLS_ASN1_BOOLEAN) and value
181  *                  in ASN.1 format.
182  *
183  * \note            This function works backwards in data buffer.
184  *
185  * \param p         The reference to the current position pointer.
186  * \param start     The start of the buffer, for bounds-checking.
187  * \param boolean   The boolean value to write, either \c 0 or \c 1.
188  *
189  * \return          The number of bytes written to \p p on success.
190  * \return          A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
191  */
192 int mbedtls_asn1_write_bool(unsigned char **p, const unsigned char *start,
193                             int boolean);
194 
195 /**
196  * \brief           Write an int tag (#MBEDTLS_ASN1_INTEGER) and value
197  *                  in ASN.1 format.
198  *
199  * \note            This function works backwards in data buffer.
200  *
201  * \param p         The reference to the current position pointer.
202  * \param start     The start of the buffer, for bounds-checking.
203  * \param val       The integer value to write.
204  *                  It must be non-negative.
205  *
206  * \return          The number of bytes written to \p p on success.
207  * \return          A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
208  */
209 int mbedtls_asn1_write_int(unsigned char **p, const unsigned char *start, int val);
210 
211 /**
212  * \brief           Write an enum tag (#MBEDTLS_ASN1_ENUMERATED) and value
213  *                  in ASN.1 format.
214  *
215  * \note            This function works backwards in data buffer.
216  *
217  * \param p         The reference to the current position pointer.
218  * \param start     The start of the buffer, for bounds-checking.
219  * \param val       The integer value to write.
220  *
221  * \return          The number of bytes written to \p p on success.
222  * \return          A negative \c MBEDTLS_ERR_ASN1_XXX error code on failure.
223  */
224 int mbedtls_asn1_write_enum(unsigned char **p, const unsigned char *start, int val);
225 
226 /**
227  * \brief           Write a string in ASN.1 format using a specific
228  *                  string encoding tag.
229 
230  * \note            This function works backwards in data buffer.
231  *
232  * \param p         The reference to the current position pointer.
233  * \param start     The start of the buffer, for bounds-checking.
234  * \param tag       The string encoding tag to write, e.g.
235  *                  #MBEDTLS_ASN1_UTF8_STRING.
236  * \param text      The string to write.
237  * \param text_len  The length of \p text in bytes (which might
238  *                  be strictly larger than the number of characters).
239  *
240  * \return          The number of bytes written to \p p on success.
241  * \return          A negative error code on failure.
242  */
243 int mbedtls_asn1_write_tagged_string(unsigned char **p, const unsigned char *start,
244                                      int tag, const char *text,
245                                      size_t text_len);
246 
247 /**
248  * \brief           Write a string in ASN.1 format using the PrintableString
249  *                  string encoding tag (#MBEDTLS_ASN1_PRINTABLE_STRING).
250  *
251  * \note            This function works backwards in data buffer.
252  *
253  * \param p         The reference to the current position pointer.
254  * \param start     The start of the buffer, for bounds-checking.
255  * \param text      The string to write.
256  * \param text_len  The length of \p text in bytes (which might
257  *                  be strictly larger than the number of characters).
258  *
259  * \return          The number of bytes written to \p p on success.
260  * \return          A negative error code on failure.
261  */
262 int mbedtls_asn1_write_printable_string(unsigned char **p,
263                                         const unsigned char *start,
264                                         const char *text, size_t text_len);
265 
266 /**
267  * \brief           Write a UTF8 string in ASN.1 format using the UTF8String
268  *                  string encoding tag (#MBEDTLS_ASN1_UTF8_STRING).
269  *
270  * \note            This function works backwards in data buffer.
271  *
272  * \param p         The reference to the current position pointer.
273  * \param start     The start of the buffer, for bounds-checking.
274  * \param text      The string to write.
275  * \param text_len  The length of \p text in bytes (which might
276  *                  be strictly larger than the number of characters).
277  *
278  * \return          The number of bytes written to \p p on success.
279  * \return          A negative error code on failure.
280  */
281 int mbedtls_asn1_write_utf8_string(unsigned char **p, const unsigned char *start,
282                                    const char *text, size_t text_len);
283 
284 /**
285  * \brief           Write a string in ASN.1 format using the IA5String
286  *                  string encoding tag (#MBEDTLS_ASN1_IA5_STRING).
287  *
288  * \note            This function works backwards in data buffer.
289  *
290  * \param p         The reference to the current position pointer.
291  * \param start     The start of the buffer, for bounds-checking.
292  * \param text      The string to write.
293  * \param text_len  The length of \p text in bytes (which might
294  *                  be strictly larger than the number of characters).
295  *
296  * \return          The number of bytes written to \p p on success.
297  * \return          A negative error code on failure.
298  */
299 int mbedtls_asn1_write_ia5_string(unsigned char **p, const unsigned char *start,
300                                   const char *text, size_t text_len);
301 
302 /**
303  * \brief           Write a bitstring tag (#MBEDTLS_ASN1_BIT_STRING) and
304  *                  value in ASN.1 format.
305  *
306  * \note            This function works backwards in data buffer.
307  *
308  * \param p         The reference to the current position pointer.
309  * \param start     The start of the buffer, for bounds-checking.
310  * \param buf       The bitstring to write.
311  * \param bits      The total number of bits in the bitstring.
312  *
313  * \return          The number of bytes written to \p p on success.
314  * \return          A negative error code on failure.
315  */
316 int mbedtls_asn1_write_bitstring(unsigned char **p, const unsigned char *start,
317                                  const unsigned char *buf, size_t bits);
318 
319 /**
320  * \brief           This function writes a named bitstring tag
321  *                  (#MBEDTLS_ASN1_BIT_STRING) and value in ASN.1 format.
322  *
323  *                  As stated in RFC 5280 Appendix B, trailing zeroes are
324  *                  omitted when encoding named bitstrings in DER.
325  *
326  * \note            This function works backwards within the data buffer.
327  *
328  * \param p         The reference to the current position pointer.
329  * \param start     The start of the buffer which is used for bounds-checking.
330  * \param buf       The bitstring to write.
331  * \param bits      The total number of bits in the bitstring.
332  *
333  * \return          The number of bytes written to \p p on success.
334  * \return          A negative error code on failure.
335  */
336 int mbedtls_asn1_write_named_bitstring(unsigned char **p,
337                                        const unsigned char *start,
338                                        const unsigned char *buf,
339                                        size_t bits);
340 
341 /**
342  * \brief           Write an octet string tag (#MBEDTLS_ASN1_OCTET_STRING)
343  *                  and value in ASN.1 format.
344  *
345  * \note            This function works backwards in data buffer.
346  *
347  * \param p         The reference to the current position pointer.
348  * \param start     The start of the buffer, for bounds-checking.
349  * \param buf       The buffer holding the data to write.
350  * \param size      The length of the data buffer \p buf.
351  *
352  * \return          The number of bytes written to \p p on success.
353  * \return          A negative error code on failure.
354  */
355 int mbedtls_asn1_write_octet_string(unsigned char **p, const unsigned char *start,
356                                     const unsigned char *buf, size_t size);
357 
358 /**
359  * \brief           Create or find a specific named_data entry for writing in a
360  *                  sequence or list based on the OID. If not already in there,
361  *                  a new entry is added to the head of the list.
362  *                  Warning: Destructive behaviour for the val data!
363  *
364  * \param list      The pointer to the location of the head of the list to seek
365  *                  through (will be updated in case of a new entry).
366  * \param oid       The OID to look for.
367  * \param oid_len   The size of the OID.
368  * \param val       The associated data to store. If this is \c NULL,
369  *                  no data is copied to the new or existing buffer.
370  * \param val_len   The minimum length of the data buffer needed.
371  *                  If this is 0, do not allocate a buffer for the associated
372  *                  data.
373  *                  If the OID was already present, enlarge, shrink or free
374  *                  the existing buffer to fit \p val_len.
375  *
376  * \return          A pointer to the new / existing entry on success.
377  * \return          \c NULL if there was a memory allocation error.
378  */
379 mbedtls_asn1_named_data *mbedtls_asn1_store_named_data(mbedtls_asn1_named_data **list,
380                                                        const char *oid, size_t oid_len,
381                                                        const unsigned char *val,
382                                                        size_t val_len);
383 
384 #ifdef __cplusplus
385 }
386 #endif
387 
388 #endif /* MBEDTLS_ASN1_WRITE_C */
389 
390 #endif /* MBEDTLS_ASN1_WRITE_H */
391