]>
git.gir.st - tmk_keyboard.git/blob - tmk_core/tool/mbed/mbed-sdk/libraries/net/https/axTLS/crypto/crypto_misc.c
2 * Copyright (c) 2007, Cameron Rich
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions are met:
9 * * Redistributions of source code must retain the above copyright notice,
10 * this list of conditions and the following disclaimer.
11 * * Redistributions in binary form must reproduce the above copyright notice,
12 * this list of conditions and the following disclaimer in the documentation
13 * and/or other materials provided with the distribution.
14 * * Neither the name of the axTLS project nor the names of its contributors
15 * may be used to endorse or promote products derived from this software
16 * without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
22 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
25 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
26 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
27 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 * Some misc. routines to help things out
42 #include "crypto_misc.h"
46 #ifdef CONFIG_WIN32_USE_CRYPTO_LIB
51 static int rng_fd
= -1;
52 #elif defined(CONFIG_WIN32_USE_CRYPTO_LIB)
53 static HCRYPTPROV gCryptProv
;
56 #if (!defined(CONFIG_USE_DEV_URANDOM) && !defined(CONFIG_WIN32_USE_CRYPTO_LIB))
57 /* change to processor registers as appropriate */
58 #define ENTROPY_POOL_SIZE 32
59 #define ENTROPY_COUNTER1 ((((uint64_t)tv.tv_sec)<<32) | tv.tv_usec)
60 #define ENTROPY_COUNTER2 rand()
61 static uint8_t entropy_pool
[ENTROPY_POOL_SIZE
];
64 const char * const unsupported_str
= "Error: Feature not supported\n";
66 #ifndef CONFIG_SSL_SKELETON_MODE
68 * Retrieve a file and put it into memory
69 * @return The size of the file, or -1 on failure.
71 int get_file(const char *filename
, uint8_t **buf
)
76 FILE *stream
= fopen(filename
, "rb");
80 #ifdef CONFIG_SSL_FULL_MODE
81 printf("file '%s' does not exist\n", filename
); TTY_FLUSH();
86 /* Win CE doesn't support stat() */
87 fseek(stream
, 0, SEEK_END
);
88 filesize
= ftell(stream
);
89 *buf
= (uint8_t *)malloc(filesize
);
90 fseek(stream
, 0, SEEK_SET
);
94 bytes_read
= fread(*buf
+total_bytes
, 1, filesize
-total_bytes
, stream
);
95 total_bytes
+= bytes_read
;
96 } while (total_bytes
< filesize
&& bytes_read
> 0);
104 * Initialise the Random Number Generator engine.
105 * - On Win32 use the platform SDK's crypto engine.
106 * - On Linux use /dev/urandom
107 * - If none of these work then use a custom RNG.
109 EXP_FUNC
void STDCALL
RNG_initialize()
111 #if !defined(WIN32) && defined(CONFIG_USE_DEV_URANDOM)
112 rng_fd
= ax_open("/dev/urandom", O_RDONLY
);
113 #elif defined(WIN32) && defined(CONFIG_WIN32_USE_CRYPTO_LIB)
114 if (!CryptAcquireContext(&gCryptProv
,
115 NULL
, NULL
, PROV_RSA_FULL
, 0))
117 if (GetLastError() == NTE_BAD_KEYSET
&&
118 !CryptAcquireContext(&gCryptProv
,
124 printf("CryptoLib: %x\n", unsupported_str
, GetLastError());
129 /* start of with a stack to copy across */
131 memcpy(entropy_pool
, &i
, ENTROPY_POOL_SIZE
);
132 srand((unsigned int)&i
);
137 * If no /dev/urandom, then initialise the RNG with something interesting.
139 EXP_FUNC
void STDCALL
RNG_custom_init(const uint8_t *seed_buf
, int size
)
141 #if defined(WIN32) || defined(CONFIG_WIN32_USE_CRYPTO_LIB)
144 for (i
= 0; i
< ENTROPY_POOL_SIZE
&& i
< size
; i
++)
145 entropy_pool
[i
] ^= seed_buf
[i
];
150 * Terminate the RNG engine.
152 EXP_FUNC
void STDCALL
RNG_terminate(void)
156 #elif defined(CONFIG_WIN32_USE_CRYPTO_LIB)
157 CryptReleaseContext(gCryptProv
, 0);
162 * Set a series of bytes with a random number. Individual bytes can be 0
164 EXP_FUNC
void STDCALL
get_random(int num_rand_bytes
, uint8_t *rand_data
)
166 #if !defined(WIN32) && defined(CONFIG_USE_DEV_URANDOM)
167 /* use the Linux default */
168 read(rng_fd
, rand_data
, num_rand_bytes
); /* read from /dev/urandom */
169 #elif defined(WIN32) && defined(CONFIG_WIN32_USE_CRYPTO_LIB)
170 /* use Microsoft Crypto Libraries */
171 CryptGenRandom(gCryptProv
, num_rand_bytes
, rand_data
);
172 #else /* nothing else to use, so use a custom RNG */
173 /* The method we use when we've got nothing better. Use RC4, time
174 and a couple of random seeds to generate a random sequence */
177 MD5_CTX rng_digest_ctx
;
178 uint8_t digest
[MD5_SIZE
];
182 /* A proper implementation would use counters etc for entropy */
183 // XXX XXX XX X need to seed this properly
184 gettimeofday(&tv
, NULL
);
185 ep
= (uint64_t *)entropy_pool
;
187 ep
[0] ^= ENTROPY_COUNTER1
;
188 ep
[1] ^= ENTROPY_COUNTER2
;
191 /* use a digested version of the entropy pool as a key */
192 MD5_Init(&rng_digest_ctx
);
193 MD5_Update(&rng_digest_ctx
, entropy_pool
, ENTROPY_POOL_SIZE
);
194 MD5_Final(digest
, &rng_digest_ctx
);
196 /* come up with the random sequence */
197 RC4_setup(&rng_ctx
, digest
, MD5_SIZE
); /* use as a key */
198 memcpy(rand_data
, entropy_pool
, num_rand_bytes
< ENTROPY_POOL_SIZE
?
199 num_rand_bytes
: ENTROPY_POOL_SIZE
);
200 RC4_crypt(&rng_ctx
, rand_data
, rand_data
, num_rand_bytes
);
202 /* move things along */
203 for (i
= ENTROPY_POOL_SIZE
-1; i
>= MD5_SIZE
; i
--)
204 entropy_pool
[i
] = entropy_pool
[i
-MD5_SIZE
];
206 /* insert the digest at the start of the entropy pool */
207 memcpy(entropy_pool
, digest
, MD5_SIZE
);
212 * Set a series of bytes with a random number. Individual bytes are not zero.
214 void get_random_NZ(int num_rand_bytes
, uint8_t *rand_data
)
217 get_random(num_rand_bytes
, rand_data
);
219 for (i
= 0; i
< num_rand_bytes
; i
++)
221 while (rand_data
[i
] == 0) /* can't be 0 */
222 rand_data
[i
] = (uint8_t)(rand());
227 * Some useful diagnostic routines
229 #if defined(CONFIG_SSL_FULL_MODE) || defined(CONFIG_DEBUG)
233 static void print_hex_init(int finish
)
239 static void print_hex(uint8_t hex
)
248 printf("%02x ", hex
);
253 else if (column
>= 16)
259 if (++hex_index
>= hex_finish
&& column
> 0)
266 * Spit out a blob of data for diagnostics. The data is is a nice column format
269 * @param format [in] The string (with possible embedded format characters)
270 * @param size [in] The number of numbers to print
271 * @param data [in] The start of data to use
272 * @param ... [in] Any additional arguments
274 EXP_FUNC
void STDCALL
print_blob(const char *format
,
275 const uint8_t *data
, int size
, ...)
282 sprintf(tmp
, "%s\n", format
);
284 print_hex_init(size
);
285 for (i
= 0; i
< size
; i
++)
294 /* VC6.0 doesn't handle variadic macros */
295 EXP_FUNC
void STDCALL
print_blob(const char *format
, const unsigned char *data
,
299 #if defined(CONFIG_SSL_HAS_PEM) || defined(CONFIG_HTTP_HAS_AUTHORIZATION)
300 /* base64 to binary lookup table */
301 static const uint8_t map
[128] =
303 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
304 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
305 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
306 255, 255, 255, 255, 255, 255, 255, 62, 255, 255, 255, 63,
307 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 255, 255,
308 255, 254, 255, 255, 255, 0, 1, 2, 3, 4, 5, 6,
309 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18,
310 19, 20, 21, 22, 23, 24, 25, 255, 255, 255, 255, 255,
311 255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36,
312 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48,
313 49, 50, 51, 255, 255, 255, 255, 255
316 EXP_FUNC
int STDCALL
base64_decode(const char *in
, int len
,
317 uint8_t *out
, int *outlen
)
324 for (x
= y
= z
= t
= 0; x
< len
; x
++)
326 if ((c
= map
[in
[x
]&0x7F]) == 0xff)
329 if (c
== 254) /* this is the end... */
336 else if (g
!= 3) /* only allow = at end */
343 out
[z
++] = (uint8_t)((t
>>16)&255);
346 out
[z
++] = (uint8_t)((t
>>8)&255);
349 out
[z
++] = (uint8_t)(t
&255);
354 /* check that we don't go past the output buffer */
366 #ifdef CONFIG_SSL_FULL_MODE
368 printf("Error: Invalid base64\n"); TTY_FLUSH();