ssl_misc.c
Go to the documentation of this file.
1 /**
2  * @file ssl_misc.c
3  * @brief SSL 3.0 helper functions
4  *
5  * @section License
6  *
7  * SPDX-License-Identifier: GPL-2.0-or-later
8  *
9  * Copyright (C) 2010-2019 Oryx Embedded SARL. All rights reserved.
10  *
11  * This file is part of CycloneSSL Open.
12  *
13  * This program is free software; you can redistribute it and/or
14  * modify it under the terms of the GNU General Public License
15  * as published by the Free Software Foundation; either version 2
16  * of the License, or (at your option) any later version.
17  *
18  * This program is distributed in the hope that it will be useful,
19  * but WITHOUT ANY WARRANTY; without even the implied warranty of
20  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  * GNU General Public License for more details.
22  *
23  * You should have received a copy of the GNU General Public License
24  * along with this program; if not, write to the Free Software Foundation,
25  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
26  *
27  * @author Oryx Embedded SARL (www.oryx-embedded.com)
28  * @version 1.9.6
29  **/
30 
31 //Switch to the appropriate trace level
32 #define TRACE_LEVEL TLS_TRACE_LEVEL
33 
34 //Dependencies
35 #include <string.h>
36 #include "core/crypto.h"
37 #include "tls.h"
38 #include "ssl_misc.h"
39 #include "debug.h"
40 
41 //Check TLS library configuration
42 #if (TLS_SUPPORT == ENABLED && TLS_MIN_VERSION <= SSL_VERSION_3_0)
43 
44 //pad1 pattern
45 const uint8_t sslPad1[48] =
46 {
47  0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
48  0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36,
49  0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36, 0x36
50 };
51 
52 //pad2 pattern
53 const uint8_t sslPad2[48] =
54 {
55  0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
56  0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C,
57  0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C, 0x5C
58 };
59 
60 
61 /**
62  * @brief Key expansion function (SSL 3.0)
63  * @param[in] secret Pointer to the secret
64  * @param[in] secretLen Length of the secret
65  * @param[in] random Pointer to the random bytes
66  * @param[in] randomLen Length of the random bytes
67  * @param[out] output Pointer to the output
68  * @param[in] outputLen Desired output length
69  * @return Error code
70  **/
71 
72 error_t sslExpandKey(const uint8_t *secret, size_t secretLen,
73  const uint8_t *random, size_t randomLen, uint8_t *output, size_t outputLen)
74 {
75  uint_t i;
76  size_t n;
77  char_t pad[16];
78  Md5Context *md5Context;
79  Sha1Context *sha1Context;
80 
81  //Output length cannot exceed 256 bytes
82  if(outputLen > (sizeof(pad) * MD5_DIGEST_SIZE))
83  return ERROR_INVALID_LENGTH;
84 
85  //Allocate a memory buffer to hold the MD5 context
86  md5Context = tlsAllocMem(sizeof(Md5Context));
87  //Failed to allocate memory?
88  if(md5Context == NULL)
89  {
90  //Report an error
91  return ERROR_OUT_OF_MEMORY;
92  }
93 
94  //Allocate a memory buffer to hold the SHA-1 context
95  sha1Context = tlsAllocMem(sizeof(Sha1Context));
96  //Failed to allocate memory?
97  if(sha1Context == NULL)
98  {
99  //Clean up side effects
100  tlsFreeMem(md5Context);
101  //Report an error
102  return ERROR_OUT_OF_MEMORY;
103  }
104 
105  //Loop until enough output has been generated
106  for(i = 0; outputLen > 0; i++)
107  {
108  //Generate pad
109  memset(pad, 'A' + i, i + 1);
110 
111  //Compute SHA(pad + secret + random)
112  sha1Init(sha1Context);
113  sha1Update(sha1Context, pad, i + 1);
114  sha1Update(sha1Context, secret, secretLen);
115  sha1Update(sha1Context, random, randomLen);
116  sha1Final(sha1Context, NULL);
117 
118  //Then compute MD5(secret + SHA(pad + secret + random))
119  md5Init(md5Context);
120  md5Update(md5Context, secret, secretLen);
121  md5Update(md5Context, sha1Context->digest, SHA1_DIGEST_SIZE);
122  md5Final(md5Context, NULL);
123 
124  //Calculate the number of bytes to copy
125  n = MIN(outputLen, MD5_DIGEST_SIZE);
126  //Copy the resulting hash value
127  memcpy(output, md5Context->digest, n);
128 
129  //Advance data pointer
130  output += n;
131  //Decrement byte counter
132  outputLen -= n;
133  }
134 
135  //Release previously allocated resources
136  tlsFreeMem(md5Context);
137  tlsFreeMem(sha1Context);
138 
139  //Successful processing
140  return NO_ERROR;
141 }
142 
143 
144 /**
145  * @brief Compute message authentication code (SSL 3.0)
146  * @param[in] encryptionEngine Pointer to the encryption/decryption engine
147  * @param[in] record Pointer to the TLS record
148  * @param[in] data Pointer to the record data
149  * @param[in] dataLen Length of the data
150  * @param[out] mac The computed MAC value
151  * @return Error code
152  **/
153 
154 error_t sslComputeMac(TlsEncryptionEngine *encryptionEngine,
155  const TlsRecord *record, const uint8_t *data, size_t dataLen, uint8_t *mac)
156 {
157  size_t padLen;
158  const HashAlgo *hashAlgo;
159  HashContext *hashContext;
160 
161  //Point to the hash algorithm to be used
162  hashAlgo = encryptionEngine->hashAlgo;
163  //Point to the hash context
164  hashContext = (HashContext *) encryptionEngine->hmacContext->hashContext;
165 
166  //The length of pad1 and pad2 depends on the hash algorithm
167  if(hashAlgo == MD5_HASH_ALGO)
168  {
169  //48-byte long patterns are used with MD5
170  padLen = 48;
171  }
172  else if(hashAlgo == SHA1_HASH_ALGO)
173  {
174  //40-byte long patterns are used with SHA-1
175  padLen = 40;
176  }
177  else
178  {
179  //SSL 3.0 supports only MD5 and SHA-1 hash functions
181  }
182 
183  //Compute hash(secret + pad1 + seqNum + type + length + data)
184  hashAlgo->init(hashContext);
185  hashAlgo->update(hashContext, encryptionEngine->macKey, encryptionEngine->macKeyLen);
186  hashAlgo->update(hashContext, sslPad1, padLen);
187  hashAlgo->update(hashContext, &encryptionEngine->seqNum, sizeof(TlsSequenceNumber));
188  hashAlgo->update(hashContext, &record->type, sizeof(record->type));
189  hashAlgo->update(hashContext, (void *) &record->length, sizeof(record->length));
190  hashAlgo->update(hashContext, data, dataLen);
191  hashAlgo->final(hashContext, mac);
192 
193  //Then compute hash(secret + pad2 + hash(secret + pad1 + seqNum + type + length + data))
194  hashAlgo->init(hashContext);
195  hashAlgo->update(hashContext, encryptionEngine->macKey, encryptionEngine->macKeyLen);
196  hashAlgo->update(hashContext, sslPad2, padLen);
197  hashAlgo->update(hashContext, mac, hashAlgo->digestSize);
198  hashAlgo->final(hashContext, mac);
199 
200  //Successful processing
201  return NO_ERROR;
202 }
203 
204 
205 /**
206  * @brief CBC padding verification (constant time)
207  * @param[in] decryptionEngine Pointer to the decryption engine
208  * @param[in] data Pointer to the record payload
209  * @param[in] dataLen Length of the payload
210  * @param[out] paddingLen Length of the padding string
211  * @return The function returns 0 if the padding is correct, 1 on failure
212  **/
213 
214 uint32_t sslVerifyPadding(TlsEncryptionEngine *decryptionEngine,
215  const uint8_t *data, size_t dataLen, size_t *paddingLen)
216 {
217  size_t i;
218  size_t n;
219  uint8_t b;
220  uint8_t mask;
221  uint32_t c;
222  uint32_t bad;
223  uint32_t bad1;
224  uint32_t bad2;
225 
226  //Retrieve the length of the padding string
227  n = data[dataLen - 1];
228 
229  //Make sure the padding length is valid
230  bad = CRYPTO_TEST_GTE_32(n, dataLen);
231 
232  //The length of the padding must be less than the cipher's block
233  //length (refer to RFC 6101, section 5.2.3.2)
234  bad |= CRYPTO_TEST_GTE_32(n, decryptionEngine->cipherAlgo->blockSize);
235 
236  //Check the first acceptable padding scheme (each byte in the padding
237  //data must be filled with the padding length value)
238  for(bad1 = 0, i = 1; i < dataLen && i < 256; i++)
239  {
240  //Read current byte
241  b = data[dataLen - 1 - i];
242 
243  //Verify that the padding string is correct
244  c = CRYPTO_TEST_LTE_32(i, n);
245  mask = CRYPTO_SELECT_8(b, n, c);
246  bad1 |= CRYPTO_TEST_NEQ_8(b, mask);
247  }
248 
249  //Check the second acceptable padding scheme (each byte in the padding
250  //data must be filled with zero)
251  for(bad2 = 0, i = 1; i < dataLen && i < 256; i++)
252  {
253  //Read current byte
254  b = data[dataLen - 1 - i];
255 
256  //Verify that the padding string is correct
257  c = CRYPTO_TEST_LTE_32(i, n);
258  mask = CRYPTO_SELECT_8(b, 0, c);
259  bad2 |= CRYPTO_TEST_NEQ_8(b, mask);
260  }
261 
262  //Verify that the padding bytes are correct
263  bad |= bad1 & bad2;
264 
265  //Save the length of the padding string
266  *paddingLen = CRYPTO_SELECT_32(n, 0, bad);
267 
268  //Return status code
269  return bad;
270 }
271 
272 
273 /**
274  * @brief MAC verification (constant time)
275  *
276  * Calculate and verify the MAC in constant time without leaking information
277  * about what the make-up of the plaintext blocks is in terms of message, MAC
278  * field and padding, and whether the format is valid (Adam Langley's method)
279  *
280  * @param[in] decryptionEngine Pointer to the decryption engine
281  * @param[in] data Pointer to the record payload
282  * @param[in] dataLen Actual length of the plaintext data (secret information)
283  * @param[in] maxDataLen Maximum possible length of the plaintext data
284  * @param[in] mac Message authentication code
285  * @return The function returns 0 if the MAC verification is successful, else 1
286  **/
287 
288 uint32_t sslVerifyMac(TlsEncryptionEngine *decryptionEngine,
289  const TlsRecord *record, const uint8_t *data, size_t dataLen,
290  size_t maxDataLen, const uint8_t *mac)
291 {
292  size_t i;
293  size_t j;
294  size_t n;
295  size_t padLen;
296  size_t headerLen;
297  size_t paddingLen;
298  size_t blockSizeMask;
299  uint8_t b;
300  uint32_t c;
301  uint64_t bitLen;
302  const HashAlgo *hashAlgo;
303  HashContext *hashContext;
304  uint8_t temp1[SHA1_DIGEST_SIZE];
305  uint8_t temp2[SHA1_DIGEST_SIZE];
306 
307  //Point to the hash algorithm to be used
308  hashAlgo = decryptionEngine->hashAlgo;
309  //Point to the hash context
310  hashContext = (HashContext *) decryptionEngine->hmacContext->hashContext;
311 
312  //The length of pad1 and pad2 depends on the hash algorithm
313  if(hashAlgo == MD5_HASH_ALGO)
314  {
315  //48-byte long patterns are used with MD5
316  padLen = 48;
317  }
318  else if(hashAlgo == SHA1_HASH_ALGO)
319  {
320  //40-byte long patterns are used with SHA-1
321  padLen = 40;
322  }
323  else
324  {
325  //SSL 3.0 supports only MD5 and SHA-1 hash functions
326  return 1;
327  }
328 
329  //The size of the block depends on the hash algorithm
330  blockSizeMask = hashAlgo->blockSize - 1;
331 
332  //Calculate the length of the additional data that will be hashed in
333  //prior to the application data
334  headerLen = decryptionEngine->macKeyLen + padLen + 11;
335 
336  //Calculate the length of the padding string
337  paddingLen = (headerLen + dataLen + hashAlgo->minPadSize - 1) & blockSizeMask;
338  paddingLen = hashAlgo->blockSize - paddingLen;
339 
340  //Length of the message, in bits
341  bitLen = (headerLen + dataLen) << 3;
342 
343  //Check endianness
344  if(hashAlgo->bigEndian)
345  {
346  //Encode the length field as a big-endian integer
347  bitLen = swapInt64(bitLen);
348  }
349 
350  //Total number of bytes to process
351  n = headerLen + maxDataLen + hashAlgo->minPadSize;
352  n = (n + hashAlgo->blockSize - 1) & ~blockSizeMask;
353  n -= headerLen;
354 
355  //Compute hash(secret + pad1 + seqNum + type + length + data)
356  hashAlgo->init(hashContext);
357  hashAlgo->update(hashContext, decryptionEngine->macKey, decryptionEngine->macKeyLen);
358  hashAlgo->update(hashContext, sslPad1, padLen);
359  hashAlgo->update(hashContext, &decryptionEngine->seqNum, sizeof(TlsSequenceNumber));
360  hashAlgo->update(hashContext, &record->type, sizeof(record->type));
361  hashAlgo->update(hashContext, (void *) &record->length, sizeof(record->length));
362 
363  //Point to the first byte of the plaintext data
364  i = 0;
365 
366  //We can process the first blocks normally because the (secret) padding
367  //length cannot affect them
368  if(maxDataLen > 255)
369  {
370  //Digest the first part of the plaintext data
371  hashAlgo->update(hashContext, data, maxDataLen - 255);
372  i += maxDataLen - 255;
373  }
374 
375  //The last blocks need to be handled carefully
376  while(i < n)
377  {
378  //Initialize the value of the current byte
379  b = 0;
380 
381  //Generate the contents of each block in constant time
382  c = CRYPTO_TEST_LT_32(i, dataLen);
383  b = CRYPTO_SELECT_8(b, data[i], c);
384 
385  c = CRYPTO_TEST_EQ_32(i, dataLen);
386  b = CRYPTO_SELECT_8(b, 0x80, c);
387 
388  j = dataLen + paddingLen;
389  c = CRYPTO_TEST_GTE_32(i, j);
390  j += 8;
391  c &= CRYPTO_TEST_LT_32(i, j);
392  b = CRYPTO_SELECT_8(b, bitLen & 0xFF, c);
393  bitLen = CRYPTO_SELECT_64(bitLen, bitLen >> 8, c);
394 
395  //Digest the current byte
396  hashAlgo->update(hashContext, &b, sizeof(uint8_t));
397 
398  //Increment byte counter
399  i++;
400 
401  //End of block detected?
402  if(((i + headerLen) & blockSizeMask) == 0)
403  {
404  //For each block we serialize the hash
405  hashAlgo->finalRaw(hashContext, temp1);
406 
407  //Check whether the current block of data is the final block
408  c = CRYPTO_TEST_EQ_32(i, dataLen + paddingLen + 8);
409 
410  //The hash is copied with a mask so that only the correct hash value
411  //is copied out, but the amount of computation remains constant
412  for(j = 0; j < hashAlgo->digestSize; j++)
413  {
414  temp2[j] = CRYPTO_SELECT_8(temp2[j], temp1[j], c);
415  }
416  }
417  }
418 
419  //Compute hash(secret + pad2 + hash(secret + pad1 + seqNum + type + length + data))
420  hashAlgo->init(hashContext);
421  hashAlgo->update(hashContext, decryptionEngine->macKey, decryptionEngine->macKeyLen);
422  hashAlgo->update(hashContext, sslPad2, padLen);
423  hashAlgo->update(hashContext, temp2, hashAlgo->digestSize);
424  hashAlgo->final(hashContext, temp1);
425 
426  //Debug message
427  TRACE_DEBUG("Read sequence number:\r\n");
428  TRACE_DEBUG_ARRAY(" ", &decryptionEngine->seqNum, sizeof(TlsSequenceNumber));
429  TRACE_DEBUG("Computed MAC:\r\n");
430  TRACE_DEBUG_ARRAY(" ", temp1, hashAlgo->digestSize);
431 
432  //The calculated MAC is bitwise compared to the received message
433  //authentication code
434  for(b = 0, i = 0; i < hashAlgo->digestSize; i++)
435  {
436  b |= mac[i] ^ temp1[i];
437  }
438 
439  //Return 0 if the message authentication code is correct, else 1
440  return CRYPTO_TEST_NEQ_8(b, 0);
441 }
442 
443 #endif
#define tlsAllocMem(size)
Definition: tls.h:757
void sha1Update(Sha1Context *context, const void *data, size_t length)
Update the SHA-1 context with a portion of the message being hashed.
Definition: sha1.c:152
HashAlgoInit init
Definition: crypto.h:1139
uint8_t digest[16]
Definition: md5.h:63
#define SHA1_HASH_ALGO
Definition: sha1.h:46
#define CRYPTO_TEST_EQ_32(a, b)
Definition: crypto.h:1025
#define CRYPTO_SELECT_32(a, b, c)
Definition: crypto.h:1049
uint8_t b[6]
Definition: dtls_misc.h:139
#define CRYPTO_TEST_GTE_32(a, b)
Definition: crypto.h:1045
size_t digestSize
Definition: crypto.h:1135
uint64_t swapInt64(uint64_t value)
Reverse the byte order of a 64-bit word.
Definition: cpu_endian.c:63
void md5Init(Md5Context *context)
Initialize MD5 message digest context.
Definition: md5.c:136
HashAlgoUpdate update
Definition: crypto.h:1140
size_t blockSize
Definition: crypto.h:1155
size_t blockSize
Definition: crypto.h:1134
@ ERROR_OUT_OF_MEMORY
Definition: error.h:63
HmacContext * hmacContext
HMAC context.
Definition: tls.h:1957
uint32_t sslVerifyMac(TlsEncryptionEngine *decryptionEngine, const TlsRecord *record, const uint8_t *data, size_t dataLen, size_t maxDataLen, const uint8_t *mac)
error_t sslComputeMac(TlsEncryptionEngine *encryptionEngine, const TlsRecord *record, const uint8_t *data, size_t dataLen, uint8_t *mac)
SSL 3.0 helper functions.
#define CRYPTO_SELECT_64(a, b, c)
Definition: crypto.h:1053
void md5Final(Md5Context *context, uint8_t *digest)
Finish the MD5 message digest.
Definition: md5.c:197
void md5Update(Md5Context *context, const void *data, size_t length)
Update the MD5 context with a portion of the message being hashed.
Definition: md5.c:158
TlsSequenceNumber seqNum
TLS sequence number.
Definition: tls.h:1961
error_t sslExpandKey(const uint8_t *secret, size_t secretLen, const uint8_t *random, size_t randomLen, uint8_t *output, size_t outputLen)
void sha1Init(Sha1Context *context)
Initialize SHA-1 message digest context.
Definition: sha1.c:129
@ ERROR_INVALID_PARAMETER
Invalid parameter.
Definition: error.h:47
error_t
Error codes.
Definition: error.h:42
#define MD5_HASH_ALGO
Definition: md5.h:46
#define CRYPTO_TEST_LT_32(a, b)
Definition: crypto.h:1033
@ ERROR_INVALID_LENGTH
Definition: error.h:109
General definitions for cryptographic algorithms.
const HashAlgo * hashAlgo
Hash algorithm for MAC operations.
Definition: tls.h:1956
uint32_t sslVerifyPadding(TlsEncryptionEngine *decryptionEngine, const uint8_t *data, size_t dataLen, size_t *paddingLen)
#define CRYPTO_SELECT_8(a, b, c)
Definition: crypto.h:977
const uint8_t sslPad1[48]
MD5 algorithm context.
Definition: md5.h:58
uint8_t mask
Definition: web_socket.h:317
Encryption engine.
Definition: tls.h:1942
#define MIN(a, b)
Definition: os_port.h:62
#define MD5_DIGEST_SIZE
Definition: md5.h:40
const uint8_t sslPad2[48]
HashAlgoFinal final
Definition: crypto.h:1141
uint8_t macKey[48]
MAC key.
Definition: tls.h:1945
#define TRACE_DEBUG(...)
Definition: debug.h:106
#define CRYPTO_TEST_LTE_32(a, b)
Definition: crypto.h:1037
char char_t
Definition: compiler_port.h:43
#define SHA1_DIGEST_SIZE
Definition: sha1.h:40
#define TRACE_DEBUG_ARRAY(p, a, n)
Definition: debug.h:107
__start_packed struct @61 TlsSequenceNumber
Sequence number.
uint8_t n
size_t minPadSize
Definition: crypto.h:1136
__start_packed struct @83 TlsRecord
TLS record.
TLS (Transport Layer Security)
SHA-1 algorithm context.
Definition: sha1.h:58
const CipherAlgo * cipherAlgo
Cipher algorithm.
Definition: tls.h:1953
uint8_t random[32]
Definition: tls.h:1614
size_t macKeyLen
Length of the MAC key.
Definition: tls.h:1946
Common interface for hash algorithms.
Definition: crypto.h:1128
uint8_t hashContext[MAX_HASH_CONTEXT_SIZE]
Definition: hmac.h:185
bool_t bigEndian
Definition: crypto.h:1137
unsigned int uint_t
Definition: compiler_port.h:45
uint8_t data[]
Definition: dtls_misc.h:176
#define tlsFreeMem(p)
Definition: tls.h:762
void sha1Final(Sha1Context *context, uint8_t *digest)
Finish the SHA-1 message digest.
Definition: sha1.c:191
Generic hash algorithm context.
Definition: crypto.h:1118
uint8_t digest[20]
Definition: sha1.h:63
#define CRYPTO_TEST_NEQ_8(a, b)
Definition: crypto.h:957
@ NO_ERROR
Success.
Definition: error.h:44
uint8_t c
Definition: ndp.h:513
Debugging facilities.
HashAlgoFinalRaw finalRaw
Definition: crypto.h:1142