]> git.sur5r.net Git - freertos/blob - FreeRTOS-Labs/Source/mbedtls/library/x509write_csr.c
Add the Labs projects provided in the V10.2.1_191129 zip file.
[freertos] / FreeRTOS-Labs / Source / mbedtls / library / x509write_csr.c
1 /*\r
2  *  X.509 Certificate Signing Request writing\r
3  *\r
4  *  Copyright (C) 2006-2015, ARM Limited, All Rights Reserved\r
5  *  SPDX-License-Identifier: Apache-2.0\r
6  *\r
7  *  Licensed under the Apache License, Version 2.0 (the "License"); you may\r
8  *  not use this file except in compliance with the License.\r
9  *  You may obtain a copy of the License at\r
10  *\r
11  *  http://www.apache.org/licenses/LICENSE-2.0\r
12  *\r
13  *  Unless required by applicable law or agreed to in writing, software\r
14  *  distributed under the License is distributed on an "AS IS" BASIS, WITHOUT\r
15  *  WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.\r
16  *  See the License for the specific language governing permissions and\r
17  *  limitations under the License.\r
18  *\r
19  *  This file is part of mbed TLS (https://tls.mbed.org)\r
20  */\r
21 /*\r
22  * References:\r
23  * - CSRs: PKCS#10 v1.7 aka RFC 2986\r
24  * - attributes: PKCS#9 v2.0 aka RFC 2985\r
25  */\r
26 \r
27 #if !defined(MBEDTLS_CONFIG_FILE)\r
28 #include "mbedtls/config.h"\r
29 #else\r
30 #include MBEDTLS_CONFIG_FILE\r
31 #endif\r
32 \r
33 #if defined(MBEDTLS_X509_CSR_WRITE_C)\r
34 \r
35 #include "mbedtls/x509_csr.h"\r
36 #include "mbedtls/oid.h"\r
37 #include "mbedtls/asn1write.h"\r
38 #include "mbedtls/platform_util.h"\r
39 \r
40 #if defined(MBEDTLS_USE_PSA_CRYPTO)\r
41 #include "psa/crypto.h"\r
42 #include "mbedtls/psa_util.h"\r
43 #endif\r
44 \r
45 #include <string.h>\r
46 #include <stdlib.h>\r
47 \r
48 #if defined(MBEDTLS_PEM_WRITE_C)\r
49 #include "mbedtls/pem.h"\r
50 #endif\r
51 \r
52 void mbedtls_x509write_csr_init( mbedtls_x509write_csr *ctx )\r
53 {\r
54     memset( ctx, 0, sizeof( mbedtls_x509write_csr ) );\r
55 }\r
56 \r
57 void mbedtls_x509write_csr_free( mbedtls_x509write_csr *ctx )\r
58 {\r
59     mbedtls_asn1_free_named_data_list( &ctx->subject );\r
60     mbedtls_asn1_free_named_data_list( &ctx->extensions );\r
61 \r
62     mbedtls_platform_zeroize( ctx, sizeof( mbedtls_x509write_csr ) );\r
63 }\r
64 \r
65 void mbedtls_x509write_csr_set_md_alg( mbedtls_x509write_csr *ctx, mbedtls_md_type_t md_alg )\r
66 {\r
67     ctx->md_alg = md_alg;\r
68 }\r
69 \r
70 void mbedtls_x509write_csr_set_key( mbedtls_x509write_csr *ctx, mbedtls_pk_context *key )\r
71 {\r
72     ctx->key = key;\r
73 }\r
74 \r
75 int mbedtls_x509write_csr_set_subject_name( mbedtls_x509write_csr *ctx,\r
76                                     const char *subject_name )\r
77 {\r
78     return mbedtls_x509_string_to_names( &ctx->subject, subject_name );\r
79 }\r
80 \r
81 int mbedtls_x509write_csr_set_extension( mbedtls_x509write_csr *ctx,\r
82                                  const char *oid, size_t oid_len,\r
83                                  const unsigned char *val, size_t val_len )\r
84 {\r
85     return mbedtls_x509_set_extension( &ctx->extensions, oid, oid_len,\r
86                                0, val, val_len );\r
87 }\r
88 \r
89 int mbedtls_x509write_csr_set_key_usage( mbedtls_x509write_csr *ctx, unsigned char key_usage )\r
90 {\r
91     unsigned char buf[4];\r
92     unsigned char *c;\r
93     int ret;\r
94 \r
95     c = buf + 4;\r
96 \r
97     ret = mbedtls_asn1_write_named_bitstring( &c, buf, &key_usage, 8 );\r
98     if( ret < 3 || ret > 4 )\r
99         return( ret );\r
100 \r
101     ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_KEY_USAGE,\r
102                                        MBEDTLS_OID_SIZE( MBEDTLS_OID_KEY_USAGE ),\r
103                                        c, (size_t)ret );\r
104     if( ret != 0 )\r
105         return( ret );\r
106 \r
107     return( 0 );\r
108 }\r
109 \r
110 int mbedtls_x509write_csr_set_ns_cert_type( mbedtls_x509write_csr *ctx,\r
111                                     unsigned char ns_cert_type )\r
112 {\r
113     unsigned char buf[4];\r
114     unsigned char *c;\r
115     int ret;\r
116 \r
117     c = buf + 4;\r
118 \r
119     ret = mbedtls_asn1_write_named_bitstring( &c, buf, &ns_cert_type, 8 );\r
120     if( ret < 3 || ret > 4 )\r
121         return( ret );\r
122 \r
123     ret = mbedtls_x509write_csr_set_extension( ctx, MBEDTLS_OID_NS_CERT_TYPE,\r
124                                        MBEDTLS_OID_SIZE( MBEDTLS_OID_NS_CERT_TYPE ),\r
125                                        c, (size_t)ret );\r
126     if( ret != 0 )\r
127         return( ret );\r
128 \r
129     return( 0 );\r
130 }\r
131 \r
132 int mbedtls_x509write_csr_der( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size,\r
133                        int (*f_rng)(void *, unsigned char *, size_t),\r
134                        void *p_rng )\r
135 {\r
136     int ret;\r
137     const char *sig_oid;\r
138     size_t sig_oid_len = 0;\r
139     unsigned char *c, *c2;\r
140     unsigned char hash[64];\r
141     unsigned char sig[MBEDTLS_MPI_MAX_SIZE];\r
142     unsigned char tmp_buf[2048];\r
143     size_t pub_len = 0, sig_and_oid_len = 0, sig_len;\r
144     size_t len = 0;\r
145     mbedtls_pk_type_t pk_alg;\r
146 #if defined(MBEDTLS_USE_PSA_CRYPTO)\r
147     psa_hash_operation_t hash_operation = PSA_HASH_OPERATION_INIT;\r
148     size_t hash_len;\r
149     psa_algorithm_t hash_alg = mbedtls_psa_translate_md( ctx->md_alg );\r
150 #endif /* MBEDTLS_USE_PSA_CRYPTO */\r
151     /*\r
152      * Prepare data to be signed in tmp_buf\r
153      */\r
154     c = tmp_buf + sizeof( tmp_buf );\r
155 \r
156     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_extensions( &c, tmp_buf, ctx->extensions ) );\r
157 \r
158     if( len )\r
159     {\r
160         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) );\r
161         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED |\r
162                                                         MBEDTLS_ASN1_SEQUENCE ) );\r
163 \r
164         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) );\r
165         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED |\r
166                                                         MBEDTLS_ASN1_SET ) );\r
167 \r
168         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( &c, tmp_buf, MBEDTLS_OID_PKCS9_CSR_EXT_REQ,\r
169                                           MBEDTLS_OID_SIZE( MBEDTLS_OID_PKCS9_CSR_EXT_REQ ) ) );\r
170 \r
171         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) );\r
172         MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED |\r
173                                                         MBEDTLS_ASN1_SEQUENCE ) );\r
174     }\r
175 \r
176     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) );\r
177     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED |\r
178                                                     MBEDTLS_ASN1_CONTEXT_SPECIFIC ) );\r
179 \r
180     MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_pk_write_pubkey_der( ctx->key,\r
181                                                 tmp_buf, c - tmp_buf ) );\r
182     c -= pub_len;\r
183     len += pub_len;\r
184 \r
185     /*\r
186      *  Subject  ::=  Name\r
187      */\r
188     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_x509_write_names( &c, tmp_buf, ctx->subject ) );\r
189 \r
190     /*\r
191      *  Version  ::=  INTEGER  {  v1(0), v2(1), v3(2)  }\r
192      */\r
193     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, tmp_buf, 0 ) );\r
194 \r
195     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, tmp_buf, len ) );\r
196     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, tmp_buf, MBEDTLS_ASN1_CONSTRUCTED |\r
197                                                     MBEDTLS_ASN1_SEQUENCE ) );\r
198 \r
199     /*\r
200      * Prepare signature\r
201      * Note: hash errors can happen only after an internal error\r
202      */\r
203 #if defined(MBEDTLS_USE_PSA_CRYPTO)\r
204     if( psa_hash_setup( &hash_operation, hash_alg ) != PSA_SUCCESS )\r
205         return( MBEDTLS_ERR_X509_FATAL_ERROR );\r
206 \r
207     if( psa_hash_update( &hash_operation, c, len ) != PSA_SUCCESS )\r
208         return( MBEDTLS_ERR_X509_FATAL_ERROR );\r
209 \r
210     if( psa_hash_finish( &hash_operation, hash, sizeof( hash ), &hash_len )\r
211         != PSA_SUCCESS )\r
212     {\r
213         return( MBEDTLS_ERR_X509_FATAL_ERROR );\r
214     }\r
215 #else /* MBEDTLS_USE_PSA_CRYPTO */\r
216     mbedtls_md( mbedtls_md_info_from_type( ctx->md_alg ), c, len, hash );\r
217 #endif\r
218     if( ( ret = mbedtls_pk_sign( ctx->key, ctx->md_alg, hash, 0, sig, &sig_len,\r
219                                  f_rng, p_rng ) ) != 0 )\r
220     {\r
221         return( ret );\r
222     }\r
223 \r
224     if( mbedtls_pk_can_do( ctx->key, MBEDTLS_PK_RSA ) )\r
225         pk_alg = MBEDTLS_PK_RSA;\r
226     else if( mbedtls_pk_can_do( ctx->key, MBEDTLS_PK_ECDSA ) )\r
227         pk_alg = MBEDTLS_PK_ECDSA;\r
228     else\r
229         return( MBEDTLS_ERR_X509_INVALID_ALG );\r
230 \r
231     if( ( ret = mbedtls_oid_get_oid_by_sig_alg( pk_alg, ctx->md_alg,\r
232                                                 &sig_oid, &sig_oid_len ) ) != 0 )\r
233     {\r
234         return( ret );\r
235     }\r
236 \r
237     /*\r
238      * Write data to output buffer\r
239      */\r
240     c2 = buf + size;\r
241     MBEDTLS_ASN1_CHK_ADD( sig_and_oid_len, mbedtls_x509_write_sig( &c2, buf,\r
242                                         sig_oid, sig_oid_len, sig, sig_len ) );\r
243 \r
244     if( len > (size_t)( c2 - buf ) )\r
245         return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL );\r
246 \r
247     c2 -= len;\r
248     memcpy( c2, c, len );\r
249 \r
250     len += sig_and_oid_len;\r
251     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c2, buf, len ) );\r
252     MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c2, buf, MBEDTLS_ASN1_CONSTRUCTED |\r
253                                                  MBEDTLS_ASN1_SEQUENCE ) );\r
254 \r
255     return( (int) len );\r
256 }\r
257 \r
258 #define PEM_BEGIN_CSR           "-----BEGIN CERTIFICATE REQUEST-----\n"\r
259 #define PEM_END_CSR             "-----END CERTIFICATE REQUEST-----\n"\r
260 \r
261 #if defined(MBEDTLS_PEM_WRITE_C)\r
262 int mbedtls_x509write_csr_pem( mbedtls_x509write_csr *ctx, unsigned char *buf, size_t size,\r
263                        int (*f_rng)(void *, unsigned char *, size_t),\r
264                        void *p_rng )\r
265 {\r
266     int ret;\r
267     unsigned char output_buf[4096];\r
268     size_t olen = 0;\r
269 \r
270     if( ( ret = mbedtls_x509write_csr_der( ctx, output_buf, sizeof(output_buf),\r
271                                    f_rng, p_rng ) ) < 0 )\r
272     {\r
273         return( ret );\r
274     }\r
275 \r
276     if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_CSR, PEM_END_CSR,\r
277                                   output_buf + sizeof(output_buf) - ret,\r
278                                   ret, buf, size, &olen ) ) != 0 )\r
279     {\r
280         return( ret );\r
281     }\r
282 \r
283     return( 0 );\r
284 }\r
285 #endif /* MBEDTLS_PEM_WRITE_C */\r
286 \r
287 #endif /* MBEDTLS_X509_CSR_WRITE_C */\r