1 /*
2  * Copyright (c) 2021-2022, Arm Limited. All rights reserved.
3  *
4  * SPDX-License-Identifier: BSD-3-Clause
5  *
6  */
7 
8 /** \file cc3xx_internal_asn1_util.h
9  *
10  * This file contains the declaration of the internal functions and
11  * utilities to perform parsing of ASN-1 encoded key buffers
12  *
13  */
14 
15 #ifndef CC3XX_INTERNAL_ASN1_UTIL_H
16 #define CC3XX_INTERNAL_ASN1_UTIL_H
17 
18 #include "psa/crypto.h"
19 
20 #include "cc_common.h"
21 #include "cc_ecc_internal.h"
22 #include "cc_ecpki_error.h"
23 #include "cc_pal_abort.h"
24 #include "cc_pal_mem.h"
25 #include "cc_pal_types.h"
26 #include "mbedtls_cc_ec_mont_edw_error.h"
27 
28 #include "cc_ecpki_build.h"
29 #include "cc_ecpki_domain.h"
30 #include "cc_ecpki_ecdsa.h"
31 #include "cc_ecpki_kg.h"
32 #include "cc_ecpki_local.h"
33 #include "pka_ec_wrst.h"
34 
35 #ifdef __cplusplus
36 extern "C" {
37 #endif
38 
39 /**
40  * \name DER constants
41  * These constants comply with the DER encoded ASN.1 type tags.
42  * DER encoding uses hexadecimal representation.
43  * An example DER sequence is:\n
44  * - 0x02 -- tag indicating INTEGER
45  * - 0x01 -- length in octets
46  * - 0x05 -- value
47  * Such sequences are typically read into \c ::mbedtls_x509_buf.
48  */
49 #define CC3XX_TAG_ASN1_INTEGER 0x02
50 #define CC3XX_TAG_ASN1_SEQUENCE 0x10
51 #define CC3XX_TAG_ASN1_CONSTRUCTED 0x20
52 
53 /**
54  * \brief           Write a length field in ASN.1 format.
55  *
56  * \note            This function works backwards in data buffer.
57  *
58  * \param p         The reference to the current position pointer.
59  * \param start     The start of the buffer, for bounds-checking.
60  * \param len       The length value to write.
61  *
62  * \return          The number of bytes written to \p p on success.
63  * \return          PSA_ERROR_BUFFER_TOO_SMALL if the buffer is too small.
64  * \return          PSA_ERROR_GENERIC_ERROR if any other error occured.
65  */
66 int cc3xx_asn1_write_len(unsigned char **p, const unsigned char *start, size_t len);
67 
68 /**
69  * \brief           Write an ASN.1 tag in ASN.1 format.
70  *
71  * \note            This function works backwards in data buffer.
72  *
73  * \param p         The reference to the current position pointer.
74  * \param start     The start of the buffer, for bounds-checking.
75  * \param tag       The tag to write.
76  *
77  * \return          The number of bytes written to \p p on success.
78  * \return          PSA_ERROR_BUFFER_TOO_SMALL if the buffer is too small.
79  */
80 int cc3xx_asn1_write_tag(unsigned char **p, const unsigned char *start,
81                          unsigned char tag);
82 
83 /**
84  * \brief           Write an int tag and value in ASN.1 format represented as a uint8_t array.
85  *
86  * \note            This function works backwards in data buffer.
87  *
88  * \param p         The reference to the current position pointer.
89  * \param start     The start of the buffer, for bounds-checking.
90  * \param data      Buffer containing the integer to be written.
91  * \param data_size Size in bytes of the integer.
92  *
93  * \return          The number of bytes written to \p p on success.
94  * \return          PSA_ERROR_BUFFER_TOO_SMALL if the buffer is too small.
95  * \return          PSA_ERROR_GENERIC_ERROR if any other error occured.
96  */
97 int cc3xx_asn1_write_big_integer(unsigned char **p, const unsigned char *start,
98                                  uint8_t *data, size_t data_size);
99 
100 /**
101  * \brief           Write an int tag and value in ASN.1 format.
102  *
103  * \note            This function works backwards in data buffer.
104  *
105  * \param p         The reference to the current position pointer.
106  * \param start     The start of the buffer, for bounds-checking.
107  * \param val       The integer value to write.
108  *                  It must be non-negative.
109  *
110  * \return          The number of bytes written to \p p on success.
111  * \return          PSA_ERROR_BUFFER_TOO_SMALL if the buffer is too small.
112  * \return          PSA_ERROR_GENERIC_ERROR if any other error occured.
113  */
114 int cc3xx_asn1_write_int(unsigned char **p, unsigned char *start, int val);
115 
116 /**
117  * \brief       Get the tag and length of the element.
118  *              Check for the requested tag.
119  *              Updates the pointer to immediately behind the tag and length.
120  *
121  * \param p     On entry, \c *p points to the start of the ASN.1 element.
122  *              On successful completion, \c *p points to the first byte
123  *              after the length, i.e. the first byte of the content.
124  *              On error, the value of \c *p is undefined.
125  * \param end   End of data.
126  * \param len   On successful completion, \c *len contains the length
127  *              read from the ASN.1 input.
128  * \param tag   The expected tag.
129  *
130  * \return      PSA_SUCCESS if successful.
131  * \return      PSA_ERROR_BUFFER_TOO_SMALL if the buffer is too small.
132  * \return      PSA_ERROR_GENERIC_ERROR if any other error occured.
133  */
134 psa_status_t cc3xx_asn1_get_tag(unsigned char **p, const unsigned char *end, size_t *len,
135                        int tag);
136 
137 /**
138  * \brief       Get the length of an ASN.1 element.
139  *              Updates the pointer to immediately behind the length.
140  *
141  * \param p     On entry, \c *p points to the first byte of the length,
142  *              i.e. immediately after the tag.
143  *              On successful completion, \c *p points to the first byte
144  *              after the length, i.e. the first byte of the content.
145  *              On error, the value of \c *p is undefined.
146  * \param end   End of data.
147  * \param len   On successful completion, \c *len contains the length
148  *              read from the ASN.1 input.
149  *
150  * \return      PSA_SUCCESS if successful.
151  * \return      PSA_ERROR_BUFFER_TOO_SMALL if the buffer is too small.
152  * \return      PSA_ERROR_GENERIC_ERROR if any other error occured.
153  */
154 psa_status_t cc3xx_asn1_get_len(unsigned char **p, const unsigned char *end,
155                        size_t *len);
156 
157 /**
158  * \brief       Retrieve an integer ASN.1 tag and its value.
159  *              Updates the pointer to immediately behind the full tag.
160  *
161  * \param p     On entry, \c *p points to the start of the ASN.1 element.
162  *              On successful completion, \c *p points to the first byte
163  *              beyond the ASN.1 element.
164  *              On error, the value of \c *p is undefined.
165  * \param end   End of data.
166  * \param val   On success, the parsed value.
167  *
168  * \return      PSA_SUCCESS if successful.
169  * \return      PSA_ERROR_BUFFER_TOO_SMALL if the buffer is too small.
170  * \return      PSA_ERROR_GENERIC_ERROR if any other error occured.
171  */
172 psa_status_t cc3xx_asn1_get_int(unsigned char **p, const unsigned char *end, int *val);
173 
174 #ifdef __cplusplus
175 }
176 #endif
177 #endif /* CC3XX_INTERNAL_ASN1_UTIL_H */
178 
179