176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* 276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Copyright (c) 2009 Joshua Oreman <oremanj@rwcr.net>. 376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * This program is free software; you can redistribute it and/or 576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * modify it under the terms of the GNU General Public License as 676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * published by the Free Software Foundation; either version 2 of the 776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * License, or any later version. 876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * This program is distributed in the hope that it will be useful, but 1076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * WITHOUT ANY WARRANTY; without even the implied warranty of 1176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 1276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * General Public License for more details. 1376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 1476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * You should have received a copy of the GNU General Public License 1576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * along with this program; if not, write to the Free Software 1676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 1776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 1876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 1976d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanFILE_LICENCE ( GPL2_OR_LATER ); 2076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 2176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <gpxe/crypto.h> 2276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <gpxe/sha1.h> 2376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <gpxe/hmac.h> 2476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <stdint.h> 2576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <byteswap.h> 2676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 2776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** 2876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * SHA1 pseudorandom function for creating derived keys 2976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 3076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v key Master key with which this call is associated 3176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v key_len Length of key 3276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v label NUL-terminated ASCII string describing purpose of PRF data 3376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v data Further data that should be included in the PRF 3476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v data_len Length of further PRF data 3576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v prf_len Bytes of PRF to generate 3676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @ret prf Pseudorandom function bytes 3776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 3876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * This is the PRF variant used by 802.11, defined in IEEE 802.11-2007 3976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 8.5.5.1. EAP-FAST uses a different SHA1-based PRF, and TLS uses an 4076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * MD5-based PRF. 4176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 4276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid prf_sha1 ( const void *key, size_t key_len, const char *label, 4376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman const void *data, size_t data_len, void *prf, size_t prf_len ) 4476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 4576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u32 blk; 4676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u8 keym[key_len]; /* modifiable copy of key */ 4776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u8 in[strlen ( label ) + 1 + data_len + 1]; /* message to HMAC */ 4876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u8 *in_blknr; /* pointer to last byte of in, block number */ 4976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u8 out[SHA1_SIZE]; /* HMAC-SHA1 result */ 5076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u8 sha1_ctx[SHA1_CTX_SIZE]; /* SHA1 context */ 5176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman const size_t label_len = strlen ( label ); 5276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 5376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* The HMAC-SHA-1 is calculated using the given key on the 5476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman message text `label', followed by a NUL, followed by one 5576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman byte indicating the block number (0 for first). */ 5676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 5776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memcpy ( keym, key, key_len ); 5876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 5976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memcpy ( in, label, strlen ( label ) + 1 ); 6076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memcpy ( in + label_len + 1, data, data_len ); 6176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman in_blknr = in + label_len + 1 + data_len; 6276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 6376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for ( blk = 0 ;; blk++ ) { 6476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman *in_blknr = blk; 6576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 6676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman hmac_init ( &sha1_algorithm, sha1_ctx, keym, &key_len ); 6776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman hmac_update ( &sha1_algorithm, sha1_ctx, in, sizeof ( in ) ); 6876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman hmac_final ( &sha1_algorithm, sha1_ctx, keym, &key_len, out ); 6976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 7076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ( prf_len <= SHA1_SIZE ) { 7176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memcpy ( prf, out, prf_len ); 7276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 7376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 7476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 7576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memcpy ( prf, out, SHA1_SIZE ); 7676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman prf_len -= SHA1_SIZE; 7776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman prf += SHA1_SIZE; 7876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 7976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 8076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 8176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** 8276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * PBKDF2 key derivation function inner block operation 8376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 8476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v passphrase Passphrase from which to derive key 8576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v pass_len Length of passphrase 8676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v salt Salt to include in key 8776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v salt_len Length of salt 8876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v iterations Number of iterations of SHA1 to perform 8976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v blocknr Index of this block, starting at 1 9076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @ret block SHA1_SIZE bytes of PBKDF2 data 9176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 9276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * The operation of this function is described in RFC 2898. 9376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 9476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void pbkdf2_sha1_f ( const void *passphrase, size_t pass_len, 9576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman const void *salt, size_t salt_len, 9676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int iterations, u32 blocknr, u8 *block ) 9776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 9876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u8 pass[pass_len]; /* modifiable passphrase */ 9976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u8 in[salt_len + 4]; /* input buffer to first round */ 10076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u8 last[SHA1_SIZE]; /* output of round N, input of N+1 */ 10176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u8 sha1_ctx[SHA1_CTX_SIZE]; 10276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u8 *next_in = in; /* changed to `last' after first round */ 10376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int next_size = sizeof ( in ); 10476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int i, j; 10576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 10676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman blocknr = htonl ( blocknr ); 10776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 10876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memcpy ( pass, passphrase, pass_len ); 10976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memcpy ( in, salt, salt_len ); 11076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memcpy ( in + salt_len, &blocknr, 4 ); 11176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memset ( block, 0, SHA1_SIZE ); 11276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 11376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for ( i = 0; i < iterations; i++ ) { 11476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman hmac_init ( &sha1_algorithm, sha1_ctx, pass, &pass_len ); 11576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman hmac_update ( &sha1_algorithm, sha1_ctx, next_in, next_size ); 11676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman hmac_final ( &sha1_algorithm, sha1_ctx, pass, &pass_len, last ); 11776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 11876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for ( j = 0; j < SHA1_SIZE; j++ ) { 11976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman block[j] ^= last[j]; 12076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 12176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 12276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman next_in = last; 12376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman next_size = SHA1_SIZE; 12476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 12576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 12676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 12776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** 12876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * PBKDF2 key derivation function using SHA1 12976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 13076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v passphrase Passphrase from which to derive key 13176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v pass_len Length of passphrase 13276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v salt Salt to include in key 13376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v salt_len Length of salt 13476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v iterations Number of iterations of SHA1 to perform 13576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v key_len Length of key to generate 13676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @ret key Generated key bytes 13776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 13876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * This is used most notably in 802.11 WPA passphrase hashing, in 13976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * which case the salt is the SSID, 4096 iterations are used, and a 14076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 32-byte key is generated that serves as the Pairwise Master Key for 14176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * EAPOL authentication. 14276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 14376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * The operation of this function is further described in RFC 2898. 14476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 14576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanvoid pbkdf2_sha1 ( const void *passphrase, size_t pass_len, 14676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman const void *salt, size_t salt_len, 14776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int iterations, void *key, size_t key_len ) 14876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman{ 14976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u32 blocks = ( key_len + SHA1_SIZE - 1 ) / SHA1_SIZE; 15076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u32 blk; 15176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman u8 buf[SHA1_SIZE]; 15276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 15376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for ( blk = 1; blk <= blocks; blk++ ) { 15476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman pbkdf2_sha1_f ( passphrase, pass_len, salt, salt_len, 15576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman iterations, blk, buf ); 15676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ( key_len <= SHA1_SIZE ) { 15776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memcpy ( key, buf, key_len ); 15876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman break; 15976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 16076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 16176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman memcpy ( key, buf, SHA1_SIZE ); 16276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman key_len -= SHA1_SIZE; 16376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman key += SHA1_SIZE; 16476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 16576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 166