Rough and ready port of axTLS

Committer:
ashleymills
Date:
Mon May 13 18:15:18 2013 +0000
Revision:
0:5a29fd060ac8
initial commit

Who changed what in which revision?

UserRevisionLine numberNew contents of line
ashleymills 0:5a29fd060ac8 1 /*
ashleymills 0:5a29fd060ac8 2 * Copyright (c) 2007, Cameron Rich
ashleymills 0:5a29fd060ac8 3 *
ashleymills 0:5a29fd060ac8 4 * All rights reserved.
ashleymills 0:5a29fd060ac8 5 *
ashleymills 0:5a29fd060ac8 6 * Redistribution and use in source and binary forms, with or without
ashleymills 0:5a29fd060ac8 7 * modification, are permitted provided that the following conditions are met:
ashleymills 0:5a29fd060ac8 8 *
ashleymills 0:5a29fd060ac8 9 * * Redistributions of source code must retain the above copyright notice,
ashleymills 0:5a29fd060ac8 10 * this list of conditions and the following disclaimer.
ashleymills 0:5a29fd060ac8 11 * * Redistributions in binary form must reproduce the above copyright notice,
ashleymills 0:5a29fd060ac8 12 * this list of conditions and the following disclaimer in the documentation
ashleymills 0:5a29fd060ac8 13 * and/or other materials provided with the distribution.
ashleymills 0:5a29fd060ac8 14 * * Neither the name of the axTLS project nor the names of its contributors
ashleymills 0:5a29fd060ac8 15 * may be used to endorse or promote products derived from this software
ashleymills 0:5a29fd060ac8 16 * without specific prior written permission.
ashleymills 0:5a29fd060ac8 17 *
ashleymills 0:5a29fd060ac8 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
ashleymills 0:5a29fd060ac8 19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
ashleymills 0:5a29fd060ac8 20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
ashleymills 0:5a29fd060ac8 21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
ashleymills 0:5a29fd060ac8 22 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
ashleymills 0:5a29fd060ac8 23 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
ashleymills 0:5a29fd060ac8 24 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
ashleymills 0:5a29fd060ac8 25 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
ashleymills 0:5a29fd060ac8 26 * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
ashleymills 0:5a29fd060ac8 27 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
ashleymills 0:5a29fd060ac8 28 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
ashleymills 0:5a29fd060ac8 29 */
ashleymills 0:5a29fd060ac8 30
ashleymills 0:5a29fd060ac8 31 /**
ashleymills 0:5a29fd060ac8 32 * SHA1 implementation - as defined in FIPS PUB 180-1 published April 17, 1995.
ashleymills 0:5a29fd060ac8 33 * This code was originally taken from RFC3174
ashleymills 0:5a29fd060ac8 34 */
ashleymills 0:5a29fd060ac8 35
ashleymills 0:5a29fd060ac8 36 #include <string.h>
ashleymills 0:5a29fd060ac8 37 #include "os_port.h"
ashleymills 0:5a29fd060ac8 38 #include "crypto.h"
ashleymills 0:5a29fd060ac8 39
ashleymills 0:5a29fd060ac8 40 /*
ashleymills 0:5a29fd060ac8 41 * Define the SHA1 circular left shift macro
ashleymills 0:5a29fd060ac8 42 */
ashleymills 0:5a29fd060ac8 43 #define SHA1CircularShift(bits,word) \
ashleymills 0:5a29fd060ac8 44 (((word) << (bits)) | ((word) >> (32-(bits))))
ashleymills 0:5a29fd060ac8 45
ashleymills 0:5a29fd060ac8 46 /* ----- static functions ----- */
ashleymills 0:5a29fd060ac8 47 static void SHA1PadMessage(SHA1_CTX *ctx);
ashleymills 0:5a29fd060ac8 48 static void SHA1ProcessMessageBlock(SHA1_CTX *ctx);
ashleymills 0:5a29fd060ac8 49
ashleymills 0:5a29fd060ac8 50 /**
ashleymills 0:5a29fd060ac8 51 * Initialize the SHA1 context
ashleymills 0:5a29fd060ac8 52 */
ashleymills 0:5a29fd060ac8 53 void SHA1_Init(SHA1_CTX *ctx)
ashleymills 0:5a29fd060ac8 54 {
ashleymills 0:5a29fd060ac8 55 ctx->Length_Low = 0;
ashleymills 0:5a29fd060ac8 56 ctx->Length_High = 0;
ashleymills 0:5a29fd060ac8 57 ctx->Message_Block_Index = 0;
ashleymills 0:5a29fd060ac8 58 ctx->Intermediate_Hash[0] = 0x67452301;
ashleymills 0:5a29fd060ac8 59 ctx->Intermediate_Hash[1] = 0xEFCDAB89;
ashleymills 0:5a29fd060ac8 60 ctx->Intermediate_Hash[2] = 0x98BADCFE;
ashleymills 0:5a29fd060ac8 61 ctx->Intermediate_Hash[3] = 0x10325476;
ashleymills 0:5a29fd060ac8 62 ctx->Intermediate_Hash[4] = 0xC3D2E1F0;
ashleymills 0:5a29fd060ac8 63 }
ashleymills 0:5a29fd060ac8 64
ashleymills 0:5a29fd060ac8 65 /**
ashleymills 0:5a29fd060ac8 66 * Accepts an array of octets as the next portion of the message.
ashleymills 0:5a29fd060ac8 67 */
ashleymills 0:5a29fd060ac8 68 void SHA1_Update(SHA1_CTX *ctx, const uint8_t *msg, int len)
ashleymills 0:5a29fd060ac8 69 {
ashleymills 0:5a29fd060ac8 70 while (len--)
ashleymills 0:5a29fd060ac8 71 {
ashleymills 0:5a29fd060ac8 72 ctx->Message_Block[ctx->Message_Block_Index++] = (*msg & 0xFF);
ashleymills 0:5a29fd060ac8 73 ctx->Length_Low += 8;
ashleymills 0:5a29fd060ac8 74
ashleymills 0:5a29fd060ac8 75 if (ctx->Length_Low == 0)
ashleymills 0:5a29fd060ac8 76 ctx->Length_High++;
ashleymills 0:5a29fd060ac8 77
ashleymills 0:5a29fd060ac8 78 if (ctx->Message_Block_Index == 64)
ashleymills 0:5a29fd060ac8 79 SHA1ProcessMessageBlock(ctx);
ashleymills 0:5a29fd060ac8 80
ashleymills 0:5a29fd060ac8 81 msg++;
ashleymills 0:5a29fd060ac8 82 }
ashleymills 0:5a29fd060ac8 83 }
ashleymills 0:5a29fd060ac8 84
ashleymills 0:5a29fd060ac8 85 /**
ashleymills 0:5a29fd060ac8 86 * Return the 160-bit message digest into the user's array
ashleymills 0:5a29fd060ac8 87 */
ashleymills 0:5a29fd060ac8 88 void SHA1_Final(uint8_t *digest, SHA1_CTX *ctx)
ashleymills 0:5a29fd060ac8 89 {
ashleymills 0:5a29fd060ac8 90 int i;
ashleymills 0:5a29fd060ac8 91
ashleymills 0:5a29fd060ac8 92 SHA1PadMessage(ctx);
ashleymills 0:5a29fd060ac8 93 memset(ctx->Message_Block, 0, 64);
ashleymills 0:5a29fd060ac8 94 ctx->Length_Low = 0; /* and clear length */
ashleymills 0:5a29fd060ac8 95 ctx->Length_High = 0;
ashleymills 0:5a29fd060ac8 96
ashleymills 0:5a29fd060ac8 97 for (i = 0; i < SHA1_SIZE; i++)
ashleymills 0:5a29fd060ac8 98 {
ashleymills 0:5a29fd060ac8 99 digest[i] = ctx->Intermediate_Hash[i>>2] >> 8 * ( 3 - ( i & 0x03 ) );
ashleymills 0:5a29fd060ac8 100 }
ashleymills 0:5a29fd060ac8 101 }
ashleymills 0:5a29fd060ac8 102
ashleymills 0:5a29fd060ac8 103 /**
ashleymills 0:5a29fd060ac8 104 * Process the next 512 bits of the message stored in the array.
ashleymills 0:5a29fd060ac8 105 */
ashleymills 0:5a29fd060ac8 106 static void SHA1ProcessMessageBlock(SHA1_CTX *ctx)
ashleymills 0:5a29fd060ac8 107 {
ashleymills 0:5a29fd060ac8 108 const uint32_t K[] = { /* Constants defined in SHA-1 */
ashleymills 0:5a29fd060ac8 109 0x5A827999,
ashleymills 0:5a29fd060ac8 110 0x6ED9EBA1,
ashleymills 0:5a29fd060ac8 111 0x8F1BBCDC,
ashleymills 0:5a29fd060ac8 112 0xCA62C1D6
ashleymills 0:5a29fd060ac8 113 };
ashleymills 0:5a29fd060ac8 114 int t; /* Loop counter */
ashleymills 0:5a29fd060ac8 115 uint32_t temp; /* Temporary word value */
ashleymills 0:5a29fd060ac8 116 uint32_t W[80]; /* Word sequence */
ashleymills 0:5a29fd060ac8 117 uint32_t A, B, C, D, E; /* Word buffers */
ashleymills 0:5a29fd060ac8 118
ashleymills 0:5a29fd060ac8 119 /*
ashleymills 0:5a29fd060ac8 120 * Initialize the first 16 words in the array W
ashleymills 0:5a29fd060ac8 121 */
ashleymills 0:5a29fd060ac8 122 for (t = 0; t < 16; t++)
ashleymills 0:5a29fd060ac8 123 {
ashleymills 0:5a29fd060ac8 124 W[t] = ctx->Message_Block[t * 4] << 24;
ashleymills 0:5a29fd060ac8 125 W[t] |= ctx->Message_Block[t * 4 + 1] << 16;
ashleymills 0:5a29fd060ac8 126 W[t] |= ctx->Message_Block[t * 4 + 2] << 8;
ashleymills 0:5a29fd060ac8 127 W[t] |= ctx->Message_Block[t * 4 + 3];
ashleymills 0:5a29fd060ac8 128 }
ashleymills 0:5a29fd060ac8 129
ashleymills 0:5a29fd060ac8 130 for (t = 16; t < 80; t++)
ashleymills 0:5a29fd060ac8 131 {
ashleymills 0:5a29fd060ac8 132 W[t] = SHA1CircularShift(1,W[t-3] ^ W[t-8] ^ W[t-14] ^ W[t-16]);
ashleymills 0:5a29fd060ac8 133 }
ashleymills 0:5a29fd060ac8 134
ashleymills 0:5a29fd060ac8 135 A = ctx->Intermediate_Hash[0];
ashleymills 0:5a29fd060ac8 136 B = ctx->Intermediate_Hash[1];
ashleymills 0:5a29fd060ac8 137 C = ctx->Intermediate_Hash[2];
ashleymills 0:5a29fd060ac8 138 D = ctx->Intermediate_Hash[3];
ashleymills 0:5a29fd060ac8 139 E = ctx->Intermediate_Hash[4];
ashleymills 0:5a29fd060ac8 140
ashleymills 0:5a29fd060ac8 141 for (t = 0; t < 20; t++)
ashleymills 0:5a29fd060ac8 142 {
ashleymills 0:5a29fd060ac8 143 temp = SHA1CircularShift(5,A) +
ashleymills 0:5a29fd060ac8 144 ((B & C) | ((~B) & D)) + E + W[t] + K[0];
ashleymills 0:5a29fd060ac8 145 E = D;
ashleymills 0:5a29fd060ac8 146 D = C;
ashleymills 0:5a29fd060ac8 147 C = SHA1CircularShift(30,B);
ashleymills 0:5a29fd060ac8 148
ashleymills 0:5a29fd060ac8 149 B = A;
ashleymills 0:5a29fd060ac8 150 A = temp;
ashleymills 0:5a29fd060ac8 151 }
ashleymills 0:5a29fd060ac8 152
ashleymills 0:5a29fd060ac8 153 for (t = 20; t < 40; t++)
ashleymills 0:5a29fd060ac8 154 {
ashleymills 0:5a29fd060ac8 155 temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[1];
ashleymills 0:5a29fd060ac8 156 E = D;
ashleymills 0:5a29fd060ac8 157 D = C;
ashleymills 0:5a29fd060ac8 158 C = SHA1CircularShift(30,B);
ashleymills 0:5a29fd060ac8 159 B = A;
ashleymills 0:5a29fd060ac8 160 A = temp;
ashleymills 0:5a29fd060ac8 161 }
ashleymills 0:5a29fd060ac8 162
ashleymills 0:5a29fd060ac8 163 for (t = 40; t < 60; t++)
ashleymills 0:5a29fd060ac8 164 {
ashleymills 0:5a29fd060ac8 165 temp = SHA1CircularShift(5,A) +
ashleymills 0:5a29fd060ac8 166 ((B & C) | (B & D) | (C & D)) + E + W[t] + K[2];
ashleymills 0:5a29fd060ac8 167 E = D;
ashleymills 0:5a29fd060ac8 168 D = C;
ashleymills 0:5a29fd060ac8 169 C = SHA1CircularShift(30,B);
ashleymills 0:5a29fd060ac8 170 B = A;
ashleymills 0:5a29fd060ac8 171 A = temp;
ashleymills 0:5a29fd060ac8 172 }
ashleymills 0:5a29fd060ac8 173
ashleymills 0:5a29fd060ac8 174 for (t = 60; t < 80; t++)
ashleymills 0:5a29fd060ac8 175 {
ashleymills 0:5a29fd060ac8 176 temp = SHA1CircularShift(5,A) + (B ^ C ^ D) + E + W[t] + K[3];
ashleymills 0:5a29fd060ac8 177 E = D;
ashleymills 0:5a29fd060ac8 178 D = C;
ashleymills 0:5a29fd060ac8 179 C = SHA1CircularShift(30,B);
ashleymills 0:5a29fd060ac8 180 B = A;
ashleymills 0:5a29fd060ac8 181 A = temp;
ashleymills 0:5a29fd060ac8 182 }
ashleymills 0:5a29fd060ac8 183
ashleymills 0:5a29fd060ac8 184 ctx->Intermediate_Hash[0] += A;
ashleymills 0:5a29fd060ac8 185 ctx->Intermediate_Hash[1] += B;
ashleymills 0:5a29fd060ac8 186 ctx->Intermediate_Hash[2] += C;
ashleymills 0:5a29fd060ac8 187 ctx->Intermediate_Hash[3] += D;
ashleymills 0:5a29fd060ac8 188 ctx->Intermediate_Hash[4] += E;
ashleymills 0:5a29fd060ac8 189 ctx->Message_Block_Index = 0;
ashleymills 0:5a29fd060ac8 190 }
ashleymills 0:5a29fd060ac8 191
ashleymills 0:5a29fd060ac8 192 /*
ashleymills 0:5a29fd060ac8 193 * According to the standard, the message must be padded to an even
ashleymills 0:5a29fd060ac8 194 * 512 bits. The first padding bit must be a '1'. The last 64
ashleymills 0:5a29fd060ac8 195 * bits represent the length of the original message. All bits in
ashleymills 0:5a29fd060ac8 196 * between should be 0. This function will pad the message
ashleymills 0:5a29fd060ac8 197 * according to those rules by filling the Message_Block array
ashleymills 0:5a29fd060ac8 198 * accordingly. It will also call the ProcessMessageBlock function
ashleymills 0:5a29fd060ac8 199 * provided appropriately. When it returns, it can be assumed that
ashleymills 0:5a29fd060ac8 200 * the message digest has been computed.
ashleymills 0:5a29fd060ac8 201 *
ashleymills 0:5a29fd060ac8 202 * @param ctx [in, out] The SHA1 context
ashleymills 0:5a29fd060ac8 203 */
ashleymills 0:5a29fd060ac8 204 static void SHA1PadMessage(SHA1_CTX *ctx)
ashleymills 0:5a29fd060ac8 205 {
ashleymills 0:5a29fd060ac8 206 /*
ashleymills 0:5a29fd060ac8 207 * Check to see if the current message block is too small to hold
ashleymills 0:5a29fd060ac8 208 * the initial padding bits and length. If so, we will pad the
ashleymills 0:5a29fd060ac8 209 * block, process it, and then continue padding into a second
ashleymills 0:5a29fd060ac8 210 * block.
ashleymills 0:5a29fd060ac8 211 */
ashleymills 0:5a29fd060ac8 212 if (ctx->Message_Block_Index > 55)
ashleymills 0:5a29fd060ac8 213 {
ashleymills 0:5a29fd060ac8 214 ctx->Message_Block[ctx->Message_Block_Index++] = 0x80;
ashleymills 0:5a29fd060ac8 215 while(ctx->Message_Block_Index < 64)
ashleymills 0:5a29fd060ac8 216 {
ashleymills 0:5a29fd060ac8 217 ctx->Message_Block[ctx->Message_Block_Index++] = 0;
ashleymills 0:5a29fd060ac8 218 }
ashleymills 0:5a29fd060ac8 219
ashleymills 0:5a29fd060ac8 220 SHA1ProcessMessageBlock(ctx);
ashleymills 0:5a29fd060ac8 221
ashleymills 0:5a29fd060ac8 222 while (ctx->Message_Block_Index < 56)
ashleymills 0:5a29fd060ac8 223 {
ashleymills 0:5a29fd060ac8 224 ctx->Message_Block[ctx->Message_Block_Index++] = 0;
ashleymills 0:5a29fd060ac8 225 }
ashleymills 0:5a29fd060ac8 226 }
ashleymills 0:5a29fd060ac8 227 else
ashleymills 0:5a29fd060ac8 228 {
ashleymills 0:5a29fd060ac8 229 ctx->Message_Block[ctx->Message_Block_Index++] = 0x80;
ashleymills 0:5a29fd060ac8 230 while(ctx->Message_Block_Index < 56)
ashleymills 0:5a29fd060ac8 231 {
ashleymills 0:5a29fd060ac8 232
ashleymills 0:5a29fd060ac8 233 ctx->Message_Block[ctx->Message_Block_Index++] = 0;
ashleymills 0:5a29fd060ac8 234 }
ashleymills 0:5a29fd060ac8 235 }
ashleymills 0:5a29fd060ac8 236
ashleymills 0:5a29fd060ac8 237 /*
ashleymills 0:5a29fd060ac8 238 * Store the message length as the last 8 octets
ashleymills 0:5a29fd060ac8 239 */
ashleymills 0:5a29fd060ac8 240 ctx->Message_Block[56] = ctx->Length_High >> 24;
ashleymills 0:5a29fd060ac8 241 ctx->Message_Block[57] = ctx->Length_High >> 16;
ashleymills 0:5a29fd060ac8 242 ctx->Message_Block[58] = ctx->Length_High >> 8;
ashleymills 0:5a29fd060ac8 243 ctx->Message_Block[59] = ctx->Length_High;
ashleymills 0:5a29fd060ac8 244 ctx->Message_Block[60] = ctx->Length_Low >> 24;
ashleymills 0:5a29fd060ac8 245 ctx->Message_Block[61] = ctx->Length_Low >> 16;
ashleymills 0:5a29fd060ac8 246 ctx->Message_Block[62] = ctx->Length_Low >> 8;
ashleymills 0:5a29fd060ac8 247 ctx->Message_Block[63] = ctx->Length_Low;
ashleymills 0:5a29fd060ac8 248 SHA1ProcessMessageBlock(ctx);
ashleymills 0:5a29fd060ac8 249 }