blob: 48158b0afd5098819c57ff166f0143d3d5e1d8ac [file] [log] [blame]
Qiufang Dai35c31332020-05-13 15:29:06 +08001/*
2 * Amazon FreeRTOS Crypto V1.0.2
3 * Copyright (C) 2017 Amazon.com, Inc. or its affiliates. All Rights Reserved.
4 *
5 * Permission is hereby granted, free of charge, to any person obtaining a copy of
6 * this software and associated documentation files (the "Software"), to deal in
7 * the Software without restriction, including without limitation the rights to
8 * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
9 * the Software, and to permit persons to whom the Software is furnished to do so,
10 * subject to the following conditions:
11 *
12 * The above copyright notice and this permission notice shall be included in all
13 * copies or substantial portions of the Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
17 * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
18 * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
19 * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 *
22 * http://aws.amazon.com/freertos
23 * http://www.FreeRTOS.org
24 */
25
26
27/* FreeRTOS includes. */
28#include "FreeRTOS.h"
29#include "FreeRTOSIPConfig.h"
30#include "aws_crypto.h"
31
32/* mbedTLS includes. */
33#include "mbedtls/config.h"
34#include "mbedtls/platform.h"
35#include "mbedtls/sha256.h"
36#include "mbedtls/sha1.h"
37#include "mbedtls/pk.h"
38#include "mbedtls/x509_crt.h"
39
40/* C runtime includes. */
41#include <string.h>
42
43/**
44 * @brief Internal signature verification context structure
45 */
46typedef struct SignatureVerificationState
47{
48 BaseType_t xAsymmetricAlgorithm;
49 BaseType_t xHashAlgorithm;
50 mbedtls_sha1_context xSHA1Context;
51 mbedtls_sha256_context xSHA256Context;
52} SignatureVerificationState_t, * SignatureVerificationStatePtr_t;
53
54/*
55 * Helper routines
56 */
57
58/**
59 * @brief Implements libc calloc semantics using the FreeRTOS heap
60 */
61static void * prvCalloc( size_t xNmemb,
62 size_t xSize )
63{
64 void * pvNew = pvPortMalloc( xNmemb * xSize );
65
66 if( NULL != pvNew )
67 {
68 memset( pvNew, 0, xNmemb * xSize );
69 }
70
71 return pvNew;
72}
73
74/**
75 * @brief Verifies a cryptographic signature based on the signer
76 * certificate, hash algorithm, and the data that was signed.
77 */
78static BaseType_t prvVerifySignature( char * pcSignerCertificate,
79 size_t xSignerCertificateLength,
80 BaseType_t xHashAlgorithm,
81 uint8_t * pucHash,
82 size_t xHashLength,
83 uint8_t * pucSignature,
84 size_t xSignatureLength )
85{
86 BaseType_t xResult = pdTRUE;
87 mbedtls_x509_crt xCertCtx;
88 mbedtls_md_type_t xMbedHashAlg = MBEDTLS_MD_SHA256;
89
90
91 memset( &xCertCtx, 0, sizeof( mbedtls_x509_crt ) );
92
93 /*
94 * Map the hash algorithm
95 */
96 if( cryptoHASH_ALGORITHM_SHA1 == xHashAlgorithm )
97 {
98 xMbedHashAlg = MBEDTLS_MD_SHA1;
99 }
100
101 /*
102 * Decode and create a certificate context
103 */
104 mbedtls_x509_crt_init( &xCertCtx );
105
106 if( 0 != mbedtls_x509_crt_parse(
107 &xCertCtx, ( const unsigned char * ) pcSignerCertificate, xSignerCertificateLength ) )
108 {
109 xResult = pdFALSE;
110 }
111
112 /*
113 * Verify the signature using the public key from the decoded certificate
114 */
115 if( pdTRUE == xResult )
116 {
117 if( 0 != mbedtls_pk_verify(
118 &xCertCtx.pk,
119 xMbedHashAlg,
120 pucHash,
121 xHashLength,
122 pucSignature,
123 xSignatureLength ) )
124 {
125 xResult = pdFALSE;
126 }
127 }
128
129 /*
130 * Clean-up
131 */
132 mbedtls_x509_crt_free( &xCertCtx );
133
134 return xResult;
135}
136
137/*
138 * Interface routines
139 */
140
141/**
142 * @brief Overrides CRT heap callouts to use FreeRTOS instead
143 */
144void CRYPTO_ConfigureHeap( void )
145{
146 /*
147 * Ensure that the FreeRTOS heap is used
148 */
149 mbedtls_platform_set_calloc_free( prvCalloc, vPortFree ); /*lint !e534 This function always return 0. */
150}
151
152/**
153 * @brief Creates signature verification context.
154 */
155BaseType_t CRYPTO_SignatureVerificationStart( void ** ppvContext,
156 BaseType_t xAsymmetricAlgorithm,
157 BaseType_t xHashAlgorithm )
158{
159 BaseType_t xResult = pdTRUE;
160 SignatureVerificationStatePtr_t pxCtx = NULL;
161
162 /*
163 * Allocate the context
164 */
165 if( NULL == ( pxCtx = ( SignatureVerificationStatePtr_t ) pvPortMalloc(
166 sizeof( *pxCtx ) ) ) ) /*lint !e9087 Allow casting void* to other types. */
167 {
168 xResult = pdFALSE;
169 }
170
171 if( pdTRUE == xResult )
172 {
173 *ppvContext = pxCtx;
174
175 /*
176 * Store the algorithm identifiers
177 */
178 pxCtx->xAsymmetricAlgorithm = xAsymmetricAlgorithm;
179 pxCtx->xHashAlgorithm = xHashAlgorithm;
180
181 /*
182 * Initialize the requested hash type
183 */
184 if( cryptoHASH_ALGORITHM_SHA1 == pxCtx->xHashAlgorithm )
185 {
186 mbedtls_sha1_init( &pxCtx->xSHA1Context );
187 ( void )mbedtls_sha1_starts_ret( &pxCtx->xSHA1Context );
188 }
189 else
190 {
191 mbedtls_sha256_init( &pxCtx->xSHA256Context );
192 ( void )mbedtls_sha256_starts_ret( &pxCtx->xSHA256Context, 0 );
193 }
194 }
195
196 return xResult;
197}
198
199/**
200 * @brief Adds bytes to an in-progress hash for subsequent signature
201 * verification.
202 */
203void CRYPTO_SignatureVerificationUpdate( void * pvContext,
204 uint8_t * pucData,
205 size_t xDataLength )
206{
207 SignatureVerificationStatePtr_t pxCtx = ( SignatureVerificationStatePtr_t ) pvContext; /*lint !e9087 Allow casting void* to other types. */
208
209 /*
210 * Add the data to the hash of the requested type
211 */
212 if( cryptoHASH_ALGORITHM_SHA1 == pxCtx->xHashAlgorithm )
213 {
214 ( void )mbedtls_sha1_update_ret( &pxCtx->xSHA1Context, pucData, xDataLength );
215 }
216 else
217 {
218 ( void )mbedtls_sha256_update_ret( &pxCtx->xSHA256Context, pucData, xDataLength );
219 }
220}
221
222/**
223 * @brief Performs signature verification on a cryptographic hash.
224 */
225BaseType_t CRYPTO_SignatureVerificationFinal( void * pvContext,
226 char * pcSignerCertificate,
227 size_t xSignerCertificateLength,
228 uint8_t * pucSignature,
229 size_t xSignatureLength )
230{
231 BaseType_t xResult = pdTRUE;
232 SignatureVerificationStatePtr_t pxCtx =
233 ( SignatureVerificationStatePtr_t ) pvContext; /*lint !e9087 Allow casting void* to other types. */
234 uint8_t ucSHA1[ cryptoSHA1_DIGEST_BYTES ];
235 uint8_t ucSHA256[ cryptoSHA256_DIGEST_BYTES ];
236 uint8_t * pucHash = NULL;
237 size_t xHashLength = 0;
238
239 /*
240 * Finish the hash
241 */
242 if( cryptoHASH_ALGORITHM_SHA1 == pxCtx->xHashAlgorithm )
243 {
244 ( void )mbedtls_sha1_finish_ret( &pxCtx->xSHA1Context, ucSHA1 );
245 pucHash = ucSHA1;
246 xHashLength = cryptoSHA1_DIGEST_BYTES;
247 }
248 else
249 {
250 ( void )mbedtls_sha256_finish_ret( &pxCtx->xSHA256Context, ucSHA256 );
251 pucHash = ucSHA256;
252 xHashLength = cryptoSHA256_DIGEST_BYTES;
253 }
254
255 /*
256 * Verify the signature
257 */
258 xResult = prvVerifySignature( pcSignerCertificate,
259 xSignerCertificateLength,
260 pxCtx->xHashAlgorithm,
261 pucHash,
262 xHashLength,
263 pucSignature,
264 xSignatureLength );
265
266 /*
267 * Clean-up
268 */
269 vPortFree( pxCtx );
270
271 return xResult;
272}