iPXE
Functions
sha1extra.c File Reference
#include <string.h>
#include <ipxe/crypto.h>
#include <ipxe/sha1.h>
#include <ipxe/hmac.h>
#include <stdint.h>
#include <byteswap.h>

Go to the source code of this file.

Functions

 FILE_LICENCE (GPL2_OR_LATER)
void prf_sha1 (const void *key, size_t key_len, const char *label, const void *data, size_t data_len, void *prf, size_t prf_len)
 SHA1 pseudorandom function for creating derived keys.
static void pbkdf2_sha1_f (const void *passphrase, size_t pass_len, const void *salt, size_t salt_len, int iterations, u32 blocknr, u8 *block)
 PBKDF2 key derivation function inner block operation.
void pbkdf2_sha1 (const void *passphrase, size_t pass_len, const void *salt, size_t salt_len, int iterations, void *key, size_t key_len)
 PBKDF2 key derivation function using SHA1.

Function Documentation

FILE_LICENCE ( GPL2_OR_LATER  )
void prf_sha1 ( const void *  key,
size_t  key_len,
const char *  label,
const void *  data,
size_t  data_len,
void *  prf,
size_t  prf_len 
)

SHA1 pseudorandom function for creating derived keys.

Parameters:
keyMaster key with which this call is associated
key_lenLength of key
labelNUL-terminated ASCII string describing purpose of PRF data
dataFurther data that should be included in the PRF
data_lenLength of further PRF data
prf_lenBytes of PRF to generate
Return values:
prfPseudorandom function bytes

This is the PRF variant used by 802.11, defined in IEEE 802.11-2007 8.5.5.1. EAP-FAST uses a different SHA1-based PRF, and TLS uses an MD5-based PRF.

Definition at line 44 of file sha1extra.c.

References hmac_final(), hmac_init(), hmac_update(), in, memcpy(), out, sha1_algorithm, SHA1_CTX_SIZE, SHA1_DIGEST_SIZE, and strlen().

Referenced by wpa_derive_ptk().

{
        u32 blk;
        u8 keym[key_len];       /* modifiable copy of key */
        u8 in[strlen ( label ) + 1 + data_len + 1]; /* message to HMAC */
        u8 *in_blknr;           /* pointer to last byte of in, block number */
        u8 out[SHA1_DIGEST_SIZE]; /* HMAC-SHA1 result */
        u8 sha1_ctx[SHA1_CTX_SIZE]; /* SHA1 context */
        const size_t label_len = strlen ( label );

        /* The HMAC-SHA-1 is calculated using the given key on the
           message text `label', followed by a NUL, followed by one
           byte indicating the block number (0 for first). */

        memcpy ( keym, key, key_len );

        memcpy ( in, label, strlen ( label ) + 1 );
        memcpy ( in + label_len + 1, data, data_len );
        in_blknr = in + label_len + 1 + data_len;

        for ( blk = 0 ;; blk++ ) {
                *in_blknr = blk;

                hmac_init ( &sha1_algorithm, sha1_ctx, keym, &key_len );
                hmac_update ( &sha1_algorithm, sha1_ctx, in, sizeof ( in ) );
                hmac_final ( &sha1_algorithm, sha1_ctx, keym, &key_len, out );

                if ( prf_len <= sizeof ( out ) ) {
                        memcpy ( prf, out, prf_len );
                        break;
                }

                memcpy ( prf, out, sizeof ( out ) );
                prf_len -= sizeof ( out );
                prf += sizeof ( out );
        }
}
static void pbkdf2_sha1_f ( const void *  passphrase,
size_t  pass_len,
const void *  salt,
size_t  salt_len,
int  iterations,
u32  blocknr,
u8 block 
) [static]

PBKDF2 key derivation function inner block operation.

Parameters:
passphrasePassphrase from which to derive key
pass_lenLength of passphrase
saltSalt to include in key
salt_lenLength of salt
iterationsNumber of iterations of SHA1 to perform
blocknrIndex of this block, starting at 1
Return values:
blockSHA1_SIZE bytes of PBKDF2 data

The operation of this function is described in RFC 2898.

Definition at line 96 of file sha1extra.c.

References hmac_final(), hmac_init(), hmac_update(), htonl, in, last, memcpy(), memset(), sha1_algorithm, SHA1_CTX_SIZE, and SHA1_DIGEST_SIZE.

Referenced by pbkdf2_sha1().

{
        u8 pass[pass_len];      /* modifiable passphrase */
        u8 in[salt_len + 4];    /* input buffer to first round */
        u8 last[SHA1_DIGEST_SIZE]; /* output of round N, input of N+1 */
        u8 sha1_ctx[SHA1_CTX_SIZE];
        u8 *next_in = in;       /* changed to `last' after first round */
        int next_size = sizeof ( in );
        int i;
        unsigned int j;

        blocknr = htonl ( blocknr );

        memcpy ( pass, passphrase, pass_len );
        memcpy ( in, salt, salt_len );
        memcpy ( in + salt_len, &blocknr, 4 );
        memset ( block, 0, sizeof ( last ) );

        for ( i = 0; i < iterations; i++ ) {
                hmac_init ( &sha1_algorithm, sha1_ctx, pass, &pass_len );
                hmac_update ( &sha1_algorithm, sha1_ctx, next_in, next_size );
                hmac_final ( &sha1_algorithm, sha1_ctx, pass, &pass_len, last );

                for ( j = 0; j < sizeof ( last ); j++ ) {
                        block[j] ^= last[j];
                }

                next_in = last;
                next_size = sizeof ( last );
        }
}
void pbkdf2_sha1 ( const void *  passphrase,
size_t  pass_len,
const void *  salt,
size_t  salt_len,
int  iterations,
void *  key,
size_t  key_len 
)

PBKDF2 key derivation function using SHA1.

Parameters:
passphrasePassphrase from which to derive key
pass_lenLength of passphrase
saltSalt to include in key
salt_lenLength of salt
iterationsNumber of iterations of SHA1 to perform
key_lenLength of key to generate
Return values:
keyGenerated key bytes

This is used most notably in 802.11 WPA passphrase hashing, in which case the salt is the SSID, 4096 iterations are used, and a 32-byte key is generated that serves as the Pairwise Master Key for EAPOL authentication.

The operation of this function is further described in RFC 2898.

Definition at line 148 of file sha1extra.c.

References blocks, memcpy(), pbkdf2_sha1_f(), and SHA1_DIGEST_SIZE.

Referenced by wpa_psk_start().

{
        u32 blocks = ( key_len + SHA1_DIGEST_SIZE - 1 ) / SHA1_DIGEST_SIZE;
        u32 blk;
        u8 buf[SHA1_DIGEST_SIZE];

        for ( blk = 1; blk <= blocks; blk++ ) {
                pbkdf2_sha1_f ( passphrase, pass_len, salt, salt_len,
                                iterations, blk, buf );
                if ( key_len <= sizeof ( buf ) ) {
                        memcpy ( key, buf, key_len );
                        break;
                }

                memcpy ( key, buf, sizeof ( buf ) );
                key_len -= sizeof ( buf );
                key += sizeof ( buf );
        }
}