iPXE
sha256.c
Go to the documentation of this file.
00001 /*
00002  * Copyright (C) 2012 Michael Brown <mbrown@fensystems.co.uk>.
00003  *
00004  * This program is free software; you can redistribute it and/or
00005  * modify it under the terms of the GNU General Public License as
00006  * published by the Free Software Foundation; either version 2 of the
00007  * License, or any later version.
00008  *
00009  * This program is distributed in the hope that it will be useful, but
00010  * WITHOUT ANY WARRANTY; without even the implied warranty of
00011  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00012  * General Public License for more details.
00013  *
00014  * You should have received a copy of the GNU General Public License
00015  * along with this program; if not, write to the Free Software
00016  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
00017  * 02110-1301, USA.
00018  *
00019  * You can also choose to distribute this program under the terms of
00020  * the Unmodified Binary Distribution Licence (as given in the file
00021  * COPYING.UBDL), provided that you have satisfied its requirements.
00022  */
00023 
00024 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
00025 
00026 /** @file
00027  *
00028  * SHA-256 algorithm
00029  *
00030  */
00031 
00032 #include <stdint.h>
00033 #include <string.h>
00034 #include <byteswap.h>
00035 #include <assert.h>
00036 #include <ipxe/rotate.h>
00037 #include <ipxe/crypto.h>
00038 #include <ipxe/asn1.h>
00039 #include <ipxe/sha256.h>
00040 
00041 /** SHA-256 variables */
00042 struct sha256_variables {
00043         /* This layout matches that of struct sha256_digest_data,
00044          * allowing for efficient endianness-conversion,
00045          */
00046         uint32_t a;
00047         uint32_t b;
00048         uint32_t c;
00049         uint32_t d;
00050         uint32_t e;
00051         uint32_t f;
00052         uint32_t g;
00053         uint32_t h;
00054         uint32_t w[SHA256_ROUNDS];
00055 } __attribute__ (( packed ));
00056 
00057 /** SHA-256 constants */
00058 static const uint32_t k[SHA256_ROUNDS] = {
00059         0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
00060         0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
00061         0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
00062         0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
00063         0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
00064         0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
00065         0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
00066         0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
00067         0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
00068         0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
00069         0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
00070 };
00071 
00072 /** SHA-256 initial digest values */
00073 static const struct sha256_digest sha256_init_digest = {
00074         .h = {
00075                 cpu_to_be32 ( 0x6a09e667 ),
00076                 cpu_to_be32 ( 0xbb67ae85 ),
00077                 cpu_to_be32 ( 0x3c6ef372 ),
00078                 cpu_to_be32 ( 0xa54ff53a ),
00079                 cpu_to_be32 ( 0x510e527f ),
00080                 cpu_to_be32 ( 0x9b05688c ),
00081                 cpu_to_be32 ( 0x1f83d9ab ),
00082                 cpu_to_be32 ( 0x5be0cd19 ),
00083         },
00084 };
00085 
00086 /**
00087  * Initialise SHA-256 family algorithm
00088  *
00089  * @v context           SHA-256 context
00090  * @v init              Initial digest values
00091  * @v digestsize        Digest size
00092  */
00093 void sha256_family_init ( struct sha256_context *context,
00094                           const struct sha256_digest *init,
00095                           size_t digestsize ) {
00096 
00097         context->len = 0;
00098         context->digestsize = digestsize;
00099         memcpy ( &context->ddd.dd.digest, init,
00100                  sizeof ( context->ddd.dd.digest ) );
00101 }
00102 
00103 /**
00104  * Initialise SHA-256 algorithm
00105  *
00106  * @v ctx               SHA-256 context
00107  */
00108 static void sha256_init ( void *ctx ) {
00109         struct sha256_context *context = ctx;
00110 
00111         sha256_family_init ( context, &sha256_init_digest,
00112                              sizeof ( struct sha256_digest ) );
00113 }
00114 
00115 /**
00116  * Calculate SHA-256 digest of accumulated data
00117  *
00118  * @v context           SHA-256 context
00119  */
00120 static void sha256_digest ( struct sha256_context *context ) {
00121         union {
00122                 union sha256_digest_data_dwords ddd;
00123                 struct sha256_variables v;
00124         } u;
00125         uint32_t *a = &u.v.a;
00126         uint32_t *b = &u.v.b;
00127         uint32_t *c = &u.v.c;
00128         uint32_t *d = &u.v.d;
00129         uint32_t *e = &u.v.e;
00130         uint32_t *f = &u.v.f;
00131         uint32_t *g = &u.v.g;
00132         uint32_t *h = &u.v.h;
00133         uint32_t *w = u.v.w;
00134         uint32_t s0;
00135         uint32_t s1;
00136         uint32_t maj;
00137         uint32_t t1;
00138         uint32_t t2;
00139         uint32_t ch;
00140         unsigned int i;
00141 
00142         /* Sanity checks */
00143         assert ( ( context->len % sizeof ( context->ddd.dd.data ) ) == 0 );
00144         linker_assert ( &u.ddd.dd.digest.h[0] == a, sha256_bad_layout );
00145         linker_assert ( &u.ddd.dd.digest.h[1] == b, sha256_bad_layout );
00146         linker_assert ( &u.ddd.dd.digest.h[2] == c, sha256_bad_layout );
00147         linker_assert ( &u.ddd.dd.digest.h[3] == d, sha256_bad_layout );
00148         linker_assert ( &u.ddd.dd.digest.h[4] == e, sha256_bad_layout );
00149         linker_assert ( &u.ddd.dd.digest.h[5] == f, sha256_bad_layout );
00150         linker_assert ( &u.ddd.dd.digest.h[6] == g, sha256_bad_layout );
00151         linker_assert ( &u.ddd.dd.digest.h[7] == h, sha256_bad_layout );
00152         linker_assert ( &u.ddd.dd.data.dword[0] == w, sha256_bad_layout );
00153 
00154         DBGC ( context, "SHA256 digesting:\n" );
00155         DBGC_HDA ( context, 0, &context->ddd.dd.digest,
00156                    sizeof ( context->ddd.dd.digest ) );
00157         DBGC_HDA ( context, context->len, &context->ddd.dd.data,
00158                    sizeof ( context->ddd.dd.data ) );
00159 
00160         /* Convert h[0..7] to host-endian, and initialise a, b, c, d,
00161          * e, f, g, h, and w[0..15]
00162          */
00163         for ( i = 0 ; i < ( sizeof ( u.ddd.dword ) /
00164                             sizeof ( u.ddd.dword[0] ) ) ; i++ ) {
00165                 be32_to_cpus ( &context->ddd.dword[i] );
00166                 u.ddd.dword[i] = context->ddd.dword[i];
00167         }
00168 
00169         /* Initialise w[16..63] */
00170         for ( i = 16 ; i < SHA256_ROUNDS ; i++ ) {
00171                 s0 = ( ror32 ( w[i-15], 7 ) ^ ror32 ( w[i-15], 18 ) ^
00172                        ( w[i-15] >> 3 ) );
00173                 s1 = ( ror32 ( w[i-2], 17 ) ^ ror32 ( w[i-2], 19 ) ^
00174                        ( w[i-2] >> 10 ) );
00175                 w[i] = ( w[i-16] + s0 + w[i-7] + s1 );
00176         }
00177 
00178         /* Main loop */
00179         for ( i = 0 ; i < SHA256_ROUNDS ; i++ ) {
00180                 s0 = ( ror32 ( *a, 2 ) ^ ror32 ( *a, 13 ) ^ ror32 ( *a, 22 ) );
00181                 maj = ( ( *a & *b ) ^ ( *a & *c ) ^ ( *b & *c ) );
00182                 t2 = ( s0 + maj );
00183                 s1 = ( ror32 ( *e, 6 ) ^ ror32 ( *e, 11 ) ^ ror32 ( *e, 25 ) );
00184                 ch = ( ( *e & *f ) ^ ( (~*e) & *g ) );
00185                 t1 = ( *h + s1 + ch + k[i] + w[i] );
00186                 *h = *g;
00187                 *g = *f;
00188                 *f = *e;
00189                 *e = ( *d + t1 );
00190                 *d = *c;
00191                 *c = *b;
00192                 *b = *a;
00193                 *a = ( t1 + t2 );
00194                 DBGC2 ( context, "%2d : %08x %08x %08x %08x %08x %08x %08x "
00195                         "%08x\n", i, *a, *b, *c, *d, *e, *f, *g, *h );
00196         }
00197 
00198         /* Add chunk to hash and convert back to big-endian */
00199         for ( i = 0 ; i < 8 ; i++ ) {
00200                 context->ddd.dd.digest.h[i] =
00201                         cpu_to_be32 ( context->ddd.dd.digest.h[i] +
00202                                       u.ddd.dd.digest.h[i] );
00203         }
00204 
00205         DBGC ( context, "SHA256 digested:\n" );
00206         DBGC_HDA ( context, 0, &context->ddd.dd.digest,
00207                    sizeof ( context->ddd.dd.digest ) );
00208 }
00209 
00210 /**
00211  * Accumulate data with SHA-256 algorithm
00212  *
00213  * @v ctx               SHA-256 context
00214  * @v data              Data
00215  * @v len               Length of data
00216  */
00217 void sha256_update ( void *ctx, const void *data, size_t len ) {
00218         struct sha256_context *context = ctx;
00219         const uint8_t *byte = data;
00220         size_t offset;
00221 
00222         /* Accumulate data a byte at a time, performing the digest
00223          * whenever we fill the data buffer
00224          */
00225         while ( len-- ) {
00226                 offset = ( context->len % sizeof ( context->ddd.dd.data ) );
00227                 context->ddd.dd.data.byte[offset] = *(byte++);
00228                 context->len++;
00229                 if ( ( context->len % sizeof ( context->ddd.dd.data ) ) == 0 )
00230                         sha256_digest ( context );
00231         }
00232 }
00233 
00234 /**
00235  * Generate SHA-256 digest
00236  *
00237  * @v ctx               SHA-256 context
00238  * @v out               Output buffer
00239  */
00240 void sha256_final ( void *ctx, void *out ) {
00241         struct sha256_context *context = ctx;
00242         uint64_t len_bits;
00243         uint8_t pad;
00244 
00245         /* Record length before pre-processing */
00246         len_bits = cpu_to_be64 ( ( ( uint64_t ) context->len ) * 8 );
00247 
00248         /* Pad with a single "1" bit followed by as many "0" bits as required */
00249         pad = 0x80;
00250         do {
00251                 sha256_update ( ctx, &pad, sizeof ( pad ) );
00252                 pad = 0x00;
00253         } while ( ( context->len % sizeof ( context->ddd.dd.data ) ) !=
00254                   offsetof ( typeof ( context->ddd.dd.data ), final.len ) );
00255 
00256         /* Append length (in bits) */
00257         sha256_update ( ctx, &len_bits, sizeof ( len_bits ) );
00258         assert ( ( context->len % sizeof ( context->ddd.dd.data ) ) == 0 );
00259 
00260         /* Copy out final digest */
00261         memcpy ( out, &context->ddd.dd.digest, context->digestsize );
00262 }
00263 
00264 /** SHA-256 algorithm */
00265 struct digest_algorithm sha256_algorithm = {
00266         .name           = "sha256",
00267         .ctxsize        = sizeof ( struct sha256_context ),
00268         .blocksize      = sizeof ( union sha256_block ),
00269         .digestsize     = sizeof ( struct sha256_digest ),
00270         .init           = sha256_init,
00271         .update         = sha256_update,
00272         .final          = sha256_final,
00273 };
00274 
00275 /** "sha256" object identifier */
00276 static uint8_t oid_sha256[] = { ASN1_OID_SHA256 };
00277 
00278 /** "sha256" OID-identified algorithm */
00279 struct asn1_algorithm oid_sha256_algorithm __asn1_algorithm = {
00280         .name = "sha256",
00281         .digest = &sha256_algorithm,
00282         .oid = ASN1_OID_CURSOR ( oid_sha256 ),
00283 };