mirror of https://gerrit.osmocom.org/libosmocore
kdf: add key derivation functions
generic sha code from git://w1.fi/hostap.git commit 5ea93947ca67ba83529798b806a15b247cdb2e93 which also happens to be the source of our milenage code. Related: SYS#5324 Change-Id: Ibf2e49edada944d91ceba62bd0d6b6ce69261fcd
This commit is contained in:
parent
e9fd81a5c3
commit
c3fa007610
|
@ -14,3 +14,4 @@ libosmocore osmo_tdef_fsm_inst_state_chg change default_timeout arg from unsigne
|
|||
libosmovty vty_read_config_filep New API
|
||||
libosmosim osim_card_{reset,close} New API
|
||||
libosmocore struct rate_ctr_group, osmo_stat_item_group_desc ABI breakage due to new struct members
|
||||
libosmgsm kdf functions New API
|
||||
|
|
|
@ -62,6 +62,7 @@ nobase_include_HEADERS = \
|
|||
osmocom/core/use_count.h \
|
||||
osmocom/crypt/auth.h \
|
||||
osmocom/crypt/gprs_cipher.h \
|
||||
osmocom/crypt/kdf.h \
|
||||
osmocom/ctrl/control_cmd.h \
|
||||
osmocom/ctrl/control_if.h \
|
||||
osmocom/ctrl/ports.h \
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
#pragma once
|
||||
|
||||
/*! \defgroup kdf key derivation functions
|
||||
* @{
|
||||
* \file kdf.h */
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
void osmo_kdf_kc128(const uint8_t* ck, const uint8_t* ik, uint8_t* kc128);
|
||||
|
||||
void osmo_kdf_kasme(const uint8_t *ck, const uint8_t *ik, const uint8_t* plmn_id,
|
||||
const uint8_t *sqn, const uint8_t *ak, uint8_t *kasme);
|
||||
|
||||
void osmo_kdf_enb(const uint8_t *kasme, uint32_t ul_count, uint8_t *kenb);
|
||||
|
||||
void osmo_kdf_nh(const uint8_t *kasme, const uint8_t *sync_input, uint8_t *nh);
|
||||
|
||||
void osmo_kdf_nas(uint8_t algo_type, uint8_t algo_id, const uint8_t *kasme, uint8_t *knas);
|
||||
|
||||
|
||||
/* @} */
|
|
@ -33,7 +33,8 @@ libgsmint_la_SOURCES = a5.c rxlev_stat.c tlv_parser.c comp128.c comp128v23.c \
|
|||
gsup.c gsup_sms.c gprs_gea.c gsm0503_conv.c oap.c gsm0808_utils.c \
|
||||
gsm23003.c gsm23236.c mncc.c bts_features.c oap_client.c \
|
||||
gsm29118.c gsm48_rest_octets.c cbsp.c gsm48049.c i460_mux.c \
|
||||
gad.c bsslap.c bssmap_le.c
|
||||
gad.c bsslap.c bssmap_le.c kdf.c
|
||||
|
||||
libgsmint_la_LDFLAGS = -no-undefined
|
||||
libgsmint_la_LIBADD = $(top_builddir)/src/libosmocore.la
|
||||
|
||||
|
@ -44,6 +45,10 @@ libosmogsm_la_LIBADD = libgsmint.la $(TALLOC_LIBS)
|
|||
if ENABLE_GNUTLS
|
||||
AM_CPPFLAGS += $(LIBGNUTLS_CFLAGS)
|
||||
libosmogsm_la_LIBADD += $(LIBGNUTLS_LIBS)
|
||||
else
|
||||
noinst_HEADERS += kdf/sha1.h kdf/sha256.h kdf/common.h kdf/sha1_i.h kdf/sha256_i.h
|
||||
libgsmint_la_SOURCES += kdf/sha256.c kdf/sha256-internal.c \
|
||||
kdf/sha1.c kdf/sha1-internal.c
|
||||
endif
|
||||
|
||||
EXTRA_DIST = libosmogsm.map
|
||||
|
|
|
@ -0,0 +1,167 @@
|
|||
/*
|
||||
* (C) 2021 by sysmocom s.f.m.c. GmbH
|
||||
*
|
||||
* Author: Eric Wild <ewild@sysmocom.de>
|
||||
*
|
||||
* All Rights Reserved
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0+
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../../config.h"
|
||||
#if (USE_GNUTLS)
|
||||
#include <gnutls/gnutls.h>
|
||||
#include <gnutls/crypto.h>
|
||||
#define HMAC_FUNC(k,lk,s,sl,out) gnutls_hmac_fast(GNUTLS_MAC_SHA256,k,lk,s,sl,out)
|
||||
#else
|
||||
#include <osmocom/crypt/kdf.h>
|
||||
#define HMAC_FUNC(k,lk,s,sl,out) hmac_sha256(k,lk,s,sl,out)
|
||||
#endif
|
||||
|
||||
#include <osmocom/core/bit32gen.h>
|
||||
#include <osmocom/crypt/kdf.h>
|
||||
|
||||
#include "kdf/common.h"
|
||||
#include "kdf/sha256.h"
|
||||
|
||||
|
||||
#if (USE_GNUTLS)
|
||||
/* gnutls < 3.3.0 requires global init.
|
||||
* gnutls >= 3.3.0 does it automatic.
|
||||
* It doesn't hurt calling it twice,
|
||||
* as long it's not done at the same time (threads).
|
||||
*/
|
||||
__attribute__((constructor))
|
||||
static void on_dso_load_gnutls(void)
|
||||
{
|
||||
if (!gnutls_check_version("3.3.0"))
|
||||
gnutls_global_init();
|
||||
}
|
||||
|
||||
__attribute__((destructor))
|
||||
static void on_dso_unload_gnutls(void)
|
||||
{
|
||||
if (!gnutls_check_version("3.3.0"))
|
||||
gnutls_global_deinit();
|
||||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* This file uses the generic key derivation function defined in 3GPP TS 33.220 Annex B
|
||||
*
|
||||
* The S parameter always consists of concatenated values FC | P0 | L0 | Pi | Li | ...
|
||||
* with Pi = Parameter number i and Li = Length of Pi (two octets)
|
||||
*
|
||||
* FC is either a single octet or two octets 0xff | FC
|
||||
* FC values ranges depend on the specification parts that use the KDF,
|
||||
* they are defined in 3GPP TS 33.220 Annex B.2.2
|
||||
*
|
||||
*/
|
||||
|
||||
/*! \addtogroup kdf
|
||||
* @{
|
||||
* key derivation functions
|
||||
*
|
||||
* \file kdf.c */
|
||||
|
||||
/* 3GPP TS 33.102 B.5 */
|
||||
void osmo_kdf_kc128(const uint8_t* ck, const uint8_t* ik, uint8_t* kc128) {
|
||||
uint8_t k[16*2];
|
||||
uint8_t s[1];
|
||||
uint8_t out_tmp256[32];
|
||||
memcpy (&k[0], ck, 16);
|
||||
memcpy (&k[16], ik, 16);
|
||||
|
||||
s[0] = 0x32; // yeah, really just one FC byte..
|
||||
|
||||
HMAC_FUNC(k, 32, s, 1, out_tmp256);
|
||||
memcpy(kc128, out_tmp256, 16);
|
||||
}
|
||||
|
||||
/* 3GPP TS 33.401 A.2 */
|
||||
void osmo_kdf_kasme(const uint8_t *ck, const uint8_t *ik, const uint8_t* plmn_id,
|
||||
const uint8_t *sqn, const uint8_t *ak, uint8_t *kasme)
|
||||
{
|
||||
uint8_t s[14];
|
||||
uint8_t k[16*2];
|
||||
int i;
|
||||
|
||||
memcpy(&k[0], ck, 16);
|
||||
memcpy(&k[16], ik, 16);
|
||||
|
||||
s[0] = 0x10;
|
||||
memcpy(&s[1], plmn_id, 3);
|
||||
s[4] = 0x00;
|
||||
s[5] = 0x03;
|
||||
|
||||
for (i = 0; i < 6; i++)
|
||||
s[6+i] = sqn[i] ^ ak[i];
|
||||
s[12] = 0x00;
|
||||
s[13] = 0x06;
|
||||
|
||||
HMAC_FUNC(k, 32, s, 14, kasme);
|
||||
}
|
||||
|
||||
/* 3GPP TS 33.401 A.3 */
|
||||
void osmo_kdf_enb(const uint8_t *kasme, uint32_t ul_count, uint8_t *kenb)
|
||||
{
|
||||
uint8_t s[7];
|
||||
|
||||
s[0] = 0x11;
|
||||
osmo_store32be(ul_count, &s[1]);
|
||||
s[5] = 0x00;
|
||||
s[6] = 0x04;
|
||||
|
||||
HMAC_FUNC(kasme, 32, s, 7, kenb);
|
||||
}
|
||||
|
||||
/* 3GPP TS 33.401 A.4 */
|
||||
void osmo_kdf_nh(const uint8_t *kasme, const uint8_t *sync_input, uint8_t *nh)
|
||||
{
|
||||
uint8_t s[35];
|
||||
|
||||
s[0] = 0x12;
|
||||
memcpy(s+1, sync_input, 32);
|
||||
s[33] = 0x00;
|
||||
s[34] = 0x20;
|
||||
|
||||
HMAC_FUNC(kasme, 32, s, 35, nh);
|
||||
}
|
||||
|
||||
/* 3GPP TS 33.401 A.7 */
|
||||
void osmo_kdf_nas(uint8_t algo_type, uint8_t algo_id, const uint8_t *kasme, uint8_t *knas)
|
||||
{
|
||||
uint8_t s[7];
|
||||
uint8_t out[32];
|
||||
|
||||
s[0] = 0x15;
|
||||
s[1] = algo_type;
|
||||
s[2] = 0x00;
|
||||
s[3] = 0x01;
|
||||
s[4] = algo_id;
|
||||
s[5] = 0x00;
|
||||
s[6] = 0x01;
|
||||
|
||||
HMAC_FUNC(kasme, 32, s, 7, out);
|
||||
memcpy(knas, out+16, 16);
|
||||
}
|
||||
|
||||
/*! @} */
|
|
@ -0,0 +1,101 @@
|
|||
#pragma once
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#define CONFIG_CRYPTO_INTERNAL
|
||||
#define TEST_FAIL() 0
|
||||
|
||||
#define MSG_DEBUG
|
||||
#define wpa_hexdump(x, args...)
|
||||
#define wpa_hexdump_key(x, args...)
|
||||
#define wpa_printf(x, args...)
|
||||
|
||||
#define os_memcpy(x, y, z) memcpy(x, y, z)
|
||||
#define os_memcmp(x, y, z) memcmp(x, y, z)
|
||||
#define os_memset(x, y, z) memset(x, y, z)
|
||||
#define os_malloc(x) malloc(x)
|
||||
#define os_free(x) free(x)
|
||||
#define os_strlen(x) strlen(x)
|
||||
|
||||
#define forced_memzero(ptr, len) memset(ptr, 0, len);
|
||||
|
||||
typedef uint64_t u64;
|
||||
typedef uint32_t u32;
|
||||
typedef uint16_t u16;
|
||||
typedef uint8_t u8;
|
||||
typedef int64_t s64;
|
||||
typedef int32_t s32;
|
||||
typedef int16_t s16;
|
||||
typedef int8_t s8;
|
||||
|
||||
|
||||
/* Macros for handling unaligned memory accesses */
|
||||
|
||||
#define WPA_GET_BE16(a) ((u16) (((a)[0] << 8) | (a)[1]))
|
||||
#define WPA_PUT_BE16(a, val) \
|
||||
do { \
|
||||
(a)[0] = ((u16) (val)) >> 8; \
|
||||
(a)[1] = ((u16) (val)) & 0xff; \
|
||||
} while (0)
|
||||
|
||||
#define WPA_GET_LE16(a) ((u16) (((a)[1] << 8) | (a)[0]))
|
||||
#define WPA_PUT_LE16(a, val) \
|
||||
do { \
|
||||
(a)[1] = ((u16) (val)) >> 8; \
|
||||
(a)[0] = ((u16) (val)) & 0xff; \
|
||||
} while (0)
|
||||
|
||||
#define WPA_GET_BE24(a) ((((u32) (a)[0]) << 16) | (((u32) (a)[1]) << 8) | \
|
||||
((u32) (a)[2]))
|
||||
#define WPA_PUT_BE24(a, val) \
|
||||
do { \
|
||||
(a)[0] = (u8) ((((u32) (val)) >> 16) & 0xff); \
|
||||
(a)[1] = (u8) ((((u32) (val)) >> 8) & 0xff); \
|
||||
(a)[2] = (u8) (((u32) (val)) & 0xff); \
|
||||
} while (0)
|
||||
|
||||
#define WPA_GET_BE32(a) ((((u32) (a)[0]) << 24) | (((u32) (a)[1]) << 16) | \
|
||||
(((u32) (a)[2]) << 8) | ((u32) (a)[3]))
|
||||
#define WPA_PUT_BE32(a, val) \
|
||||
do { \
|
||||
(a)[0] = (u8) ((((u32) (val)) >> 24) & 0xff); \
|
||||
(a)[1] = (u8) ((((u32) (val)) >> 16) & 0xff); \
|
||||
(a)[2] = (u8) ((((u32) (val)) >> 8) & 0xff); \
|
||||
(a)[3] = (u8) (((u32) (val)) & 0xff); \
|
||||
} while (0)
|
||||
|
||||
#define WPA_GET_LE32(a) ((((u32) (a)[3]) << 24) | (((u32) (a)[2]) << 16) | \
|
||||
(((u32) (a)[1]) << 8) | ((u32) (a)[0]))
|
||||
#define WPA_PUT_LE32(a, val) \
|
||||
do { \
|
||||
(a)[3] = (u8) ((((u32) (val)) >> 24) & 0xff); \
|
||||
(a)[2] = (u8) ((((u32) (val)) >> 16) & 0xff); \
|
||||
(a)[1] = (u8) ((((u32) (val)) >> 8) & 0xff); \
|
||||
(a)[0] = (u8) (((u32) (val)) & 0xff); \
|
||||
} while (0)
|
||||
|
||||
#define WPA_GET_BE64(a) ((((u64) (a)[0]) << 56) | (((u64) (a)[1]) << 48) | \
|
||||
(((u64) (a)[2]) << 40) | (((u64) (a)[3]) << 32) | \
|
||||
(((u64) (a)[4]) << 24) | (((u64) (a)[5]) << 16) | \
|
||||
(((u64) (a)[6]) << 8) | ((u64) (a)[7]))
|
||||
#define WPA_PUT_BE64(a, val) \
|
||||
do { \
|
||||
(a)[0] = (u8) (((u64) (val)) >> 56); \
|
||||
(a)[1] = (u8) (((u64) (val)) >> 48); \
|
||||
(a)[2] = (u8) (((u64) (val)) >> 40); \
|
||||
(a)[3] = (u8) (((u64) (val)) >> 32); \
|
||||
(a)[4] = (u8) (((u64) (val)) >> 24); \
|
||||
(a)[5] = (u8) (((u64) (val)) >> 16); \
|
||||
(a)[6] = (u8) (((u64) (val)) >> 8); \
|
||||
(a)[7] = (u8) (((u64) (val)) & 0xff); \
|
||||
} while (0)
|
||||
|
||||
#define WPA_GET_LE64(a) ((((u64) (a)[7]) << 56) | (((u64) (a)[6]) << 48) | \
|
||||
(((u64) (a)[5]) << 40) | (((u64) (a)[4]) << 32) | \
|
||||
(((u64) (a)[3]) << 24) | (((u64) (a)[2]) << 16) | \
|
||||
(((u64) (a)[1]) << 8) | ((u64) (a)[0]))
|
||||
|
||||
|
||||
#define __must_check
|
|
@ -0,0 +1,470 @@
|
|||
/*
|
||||
* WPA Supplicant / wrapper functions for crypto libraries
|
||||
* Copyright (c) 2004-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*
|
||||
* This file defines the cryptographic functions that need to be implemented
|
||||
* for wpa_supplicant and hostapd. When TLS is not used, internal
|
||||
* implementation of MD5, SHA1, and AES is used and no external libraries are
|
||||
* required. When TLS is enabled (e.g., by enabling EAP-TLS or EAP-PEAP), the
|
||||
* crypto library used by the TLS implementation is expected to be used for
|
||||
* non-TLS needs, too, in order to save space by not implementing these
|
||||
* functions twice.
|
||||
*
|
||||
* Wrapper code for using each crypto library is in its own file (crypto*.c)
|
||||
* and one of these files is build and linked in to provide the functions
|
||||
* defined here.
|
||||
*/
|
||||
|
||||
#ifndef CRYPTO_H
|
||||
#define CRYPTO_H
|
||||
|
||||
/**
|
||||
* md4_vector - MD4 hash for data vector
|
||||
* @num_elem: Number of elements in the data vector
|
||||
* @addr: Pointers to the data areas
|
||||
* @len: Lengths of the data blocks
|
||||
* @mac: Buffer for the hash
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int md4_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac);
|
||||
|
||||
/**
|
||||
* md5_vector - MD5 hash for data vector
|
||||
* @num_elem: Number of elements in the data vector
|
||||
* @addr: Pointers to the data areas
|
||||
* @len: Lengths of the data blocks
|
||||
* @mac: Buffer for the hash
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int md5_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac);
|
||||
|
||||
#ifdef CONFIG_FIPS
|
||||
/**
|
||||
* md5_vector_non_fips_allow - MD5 hash for data vector (non-FIPS use allowed)
|
||||
* @num_elem: Number of elements in the data vector
|
||||
* @addr: Pointers to the data areas
|
||||
* @len: Lengths of the data blocks
|
||||
* @mac: Buffer for the hash
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int md5_vector_non_fips_allow(size_t num_elem, const u8 *addr[],
|
||||
const size_t *len, u8 *mac);
|
||||
#else /* CONFIG_FIPS */
|
||||
#define md5_vector_non_fips_allow md5_vector
|
||||
#endif /* CONFIG_FIPS */
|
||||
|
||||
|
||||
/**
|
||||
* sha1_vector - SHA-1 hash for data vector
|
||||
* @num_elem: Number of elements in the data vector
|
||||
* @addr: Pointers to the data areas
|
||||
* @len: Lengths of the data blocks
|
||||
* @mac: Buffer for the hash
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len,
|
||||
u8 *mac);
|
||||
|
||||
/**
|
||||
* fips186_2-prf - NIST FIPS Publication 186-2 change notice 1 PRF
|
||||
* @seed: Seed/key for the PRF
|
||||
* @seed_len: Seed length in bytes
|
||||
* @x: Buffer for PRF output
|
||||
* @xlen: Output length in bytes
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*
|
||||
* This function implements random number generation specified in NIST FIPS
|
||||
* Publication 186-2 for EAP-SIM. This PRF uses a function that is similar to
|
||||
* SHA-1, but has different message padding.
|
||||
*/
|
||||
int __must_check fips186_2_prf(const u8 *seed, size_t seed_len, u8 *x,
|
||||
size_t xlen);
|
||||
|
||||
/**
|
||||
* sha256_vector - SHA256 hash for data vector
|
||||
* @num_elem: Number of elements in the data vector
|
||||
* @addr: Pointers to the data areas
|
||||
* @len: Lengths of the data blocks
|
||||
* @mac: Buffer for the hash
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len,
|
||||
u8 *mac);
|
||||
|
||||
/**
|
||||
* des_encrypt - Encrypt one block with DES
|
||||
* @clear: 8 octets (in)
|
||||
* @key: 7 octets (in) (no parity bits included)
|
||||
* @cypher: 8 octets (out)
|
||||
*/
|
||||
void des_encrypt(const u8 *clear, const u8 *key, u8 *cypher);
|
||||
|
||||
/**
|
||||
* aes_encrypt_init - Initialize AES for encryption
|
||||
* @key: Encryption key
|
||||
* @len: Key length in bytes (usually 16, i.e., 128 bits)
|
||||
* Returns: Pointer to context data or %NULL on failure
|
||||
*/
|
||||
void * aes_encrypt_init(const u8 *key, size_t len);
|
||||
|
||||
/**
|
||||
* aes_encrypt - Encrypt one AES block
|
||||
* @ctx: Context pointer from aes_encrypt_init()
|
||||
* @plain: Plaintext data to be encrypted (16 bytes)
|
||||
* @crypt: Buffer for the encrypted data (16 bytes)
|
||||
*/
|
||||
void aes_encrypt(void *ctx, const u8 *plain, u8 *crypt);
|
||||
|
||||
/**
|
||||
* aes_encrypt_deinit - Deinitialize AES encryption
|
||||
* @ctx: Context pointer from aes_encrypt_init()
|
||||
*/
|
||||
void aes_encrypt_deinit(void *ctx);
|
||||
|
||||
/**
|
||||
* aes_decrypt_init - Initialize AES for decryption
|
||||
* @key: Decryption key
|
||||
* @len: Key length in bytes (usually 16, i.e., 128 bits)
|
||||
* Returns: Pointer to context data or %NULL on failure
|
||||
*/
|
||||
void * aes_decrypt_init(const u8 *key, size_t len);
|
||||
|
||||
/**
|
||||
* aes_decrypt - Decrypt one AES block
|
||||
* @ctx: Context pointer from aes_encrypt_init()
|
||||
* @crypt: Encrypted data (16 bytes)
|
||||
* @plain: Buffer for the decrypted data (16 bytes)
|
||||
*/
|
||||
void aes_decrypt(void *ctx, const u8 *crypt, u8 *plain);
|
||||
|
||||
/**
|
||||
* aes_decrypt_deinit - Deinitialize AES decryption
|
||||
* @ctx: Context pointer from aes_encrypt_init()
|
||||
*/
|
||||
void aes_decrypt_deinit(void *ctx);
|
||||
|
||||
|
||||
enum crypto_hash_alg {
|
||||
CRYPTO_HASH_ALG_MD5, CRYPTO_HASH_ALG_SHA1,
|
||||
CRYPTO_HASH_ALG_HMAC_MD5, CRYPTO_HASH_ALG_HMAC_SHA1,
|
||||
CRYPTO_HASH_ALG_SHA256, CRYPTO_HASH_ALG_HMAC_SHA256
|
||||
};
|
||||
|
||||
struct crypto_hash;
|
||||
|
||||
/**
|
||||
* crypto_hash_init - Initialize hash/HMAC function
|
||||
* @alg: Hash algorithm
|
||||
* @key: Key for keyed hash (e.g., HMAC) or %NULL if not needed
|
||||
* @key_len: Length of the key in bytes
|
||||
* Returns: Pointer to hash context to use with other hash functions or %NULL
|
||||
* on failure
|
||||
*
|
||||
* This function is only used with internal TLSv1 implementation
|
||||
* (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
|
||||
* to implement this.
|
||||
*/
|
||||
struct crypto_hash * crypto_hash_init(enum crypto_hash_alg alg, const u8 *key,
|
||||
size_t key_len);
|
||||
|
||||
/**
|
||||
* crypto_hash_update - Add data to hash calculation
|
||||
* @ctx: Context pointer from crypto_hash_init()
|
||||
* @data: Data buffer to add
|
||||
* @len: Length of the buffer
|
||||
*
|
||||
* This function is only used with internal TLSv1 implementation
|
||||
* (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
|
||||
* to implement this.
|
||||
*/
|
||||
void crypto_hash_update(struct crypto_hash *ctx, const u8 *data, size_t len);
|
||||
|
||||
/**
|
||||
* crypto_hash_finish - Complete hash calculation
|
||||
* @ctx: Context pointer from crypto_hash_init()
|
||||
* @hash: Buffer for hash value or %NULL if caller is just freeing the hash
|
||||
* context
|
||||
* @len: Pointer to length of the buffer or %NULL if caller is just freeing the
|
||||
* hash context; on return, this is set to the actual length of the hash value
|
||||
* Returns: 0 on success, -1 if buffer is too small (len set to needed length),
|
||||
* or -2 on other failures (including failed crypto_hash_update() operations)
|
||||
*
|
||||
* This function calculates the hash value and frees the context buffer that
|
||||
* was used for hash calculation.
|
||||
*
|
||||
* This function is only used with internal TLSv1 implementation
|
||||
* (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
|
||||
* to implement this.
|
||||
*/
|
||||
int crypto_hash_finish(struct crypto_hash *ctx, u8 *hash, size_t *len);
|
||||
|
||||
|
||||
enum crypto_cipher_alg {
|
||||
CRYPTO_CIPHER_NULL = 0, CRYPTO_CIPHER_ALG_AES, CRYPTO_CIPHER_ALG_3DES,
|
||||
CRYPTO_CIPHER_ALG_DES, CRYPTO_CIPHER_ALG_RC2, CRYPTO_CIPHER_ALG_RC4
|
||||
};
|
||||
|
||||
struct crypto_cipher;
|
||||
|
||||
/**
|
||||
* crypto_cipher_init - Initialize block/stream cipher function
|
||||
* @alg: Cipher algorithm
|
||||
* @iv: Initialization vector for block ciphers or %NULL for stream ciphers
|
||||
* @key: Cipher key
|
||||
* @key_len: Length of key in bytes
|
||||
* Returns: Pointer to cipher context to use with other cipher functions or
|
||||
* %NULL on failure
|
||||
*
|
||||
* This function is only used with internal TLSv1 implementation
|
||||
* (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
|
||||
* to implement this.
|
||||
*/
|
||||
struct crypto_cipher * crypto_cipher_init(enum crypto_cipher_alg alg,
|
||||
const u8 *iv, const u8 *key,
|
||||
size_t key_len);
|
||||
|
||||
/**
|
||||
* crypto_cipher_encrypt - Cipher encrypt
|
||||
* @ctx: Context pointer from crypto_cipher_init()
|
||||
* @plain: Plaintext to cipher
|
||||
* @crypt: Resulting ciphertext
|
||||
* @len: Length of the plaintext
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*
|
||||
* This function is only used with internal TLSv1 implementation
|
||||
* (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
|
||||
* to implement this.
|
||||
*/
|
||||
int __must_check crypto_cipher_encrypt(struct crypto_cipher *ctx,
|
||||
const u8 *plain, u8 *crypt, size_t len);
|
||||
|
||||
/**
|
||||
* crypto_cipher_decrypt - Cipher decrypt
|
||||
* @ctx: Context pointer from crypto_cipher_init()
|
||||
* @crypt: Ciphertext to decrypt
|
||||
* @plain: Resulting plaintext
|
||||
* @len: Length of the cipher text
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*
|
||||
* This function is only used with internal TLSv1 implementation
|
||||
* (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
|
||||
* to implement this.
|
||||
*/
|
||||
int __must_check crypto_cipher_decrypt(struct crypto_cipher *ctx,
|
||||
const u8 *crypt, u8 *plain, size_t len);
|
||||
|
||||
/**
|
||||
* crypto_cipher_decrypt - Free cipher context
|
||||
* @ctx: Context pointer from crypto_cipher_init()
|
||||
*
|
||||
* This function is only used with internal TLSv1 implementation
|
||||
* (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
|
||||
* to implement this.
|
||||
*/
|
||||
void crypto_cipher_deinit(struct crypto_cipher *ctx);
|
||||
|
||||
|
||||
struct crypto_public_key;
|
||||
struct crypto_private_key;
|
||||
|
||||
/**
|
||||
* crypto_public_key_import - Import an RSA public key
|
||||
* @key: Key buffer (DER encoded RSA public key)
|
||||
* @len: Key buffer length in bytes
|
||||
* Returns: Pointer to the public key or %NULL on failure
|
||||
*
|
||||
* This function can just return %NULL if the crypto library supports X.509
|
||||
* parsing. In that case, crypto_public_key_from_cert() is used to import the
|
||||
* public key from a certificate.
|
||||
*
|
||||
* This function is only used with internal TLSv1 implementation
|
||||
* (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
|
||||
* to implement this.
|
||||
*/
|
||||
struct crypto_public_key * crypto_public_key_import(const u8 *key, size_t len);
|
||||
|
||||
/**
|
||||
* crypto_private_key_import - Import an RSA private key
|
||||
* @key: Key buffer (DER encoded RSA private key)
|
||||
* @len: Key buffer length in bytes
|
||||
* @passwd: Key encryption password or %NULL if key is not encrypted
|
||||
* Returns: Pointer to the private key or %NULL on failure
|
||||
*
|
||||
* This function is only used with internal TLSv1 implementation
|
||||
* (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
|
||||
* to implement this.
|
||||
*/
|
||||
struct crypto_private_key * crypto_private_key_import(const u8 *key,
|
||||
size_t len,
|
||||
const char *passwd);
|
||||
|
||||
/**
|
||||
* crypto_public_key_from_cert - Import an RSA public key from a certificate
|
||||
* @buf: DER encoded X.509 certificate
|
||||
* @len: Certificate buffer length in bytes
|
||||
* Returns: Pointer to public key or %NULL on failure
|
||||
*
|
||||
* This function can just return %NULL if the crypto library does not support
|
||||
* X.509 parsing. In that case, internal code will be used to parse the
|
||||
* certificate and public key is imported using crypto_public_key_import().
|
||||
*
|
||||
* This function is only used with internal TLSv1 implementation
|
||||
* (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
|
||||
* to implement this.
|
||||
*/
|
||||
struct crypto_public_key * crypto_public_key_from_cert(const u8 *buf,
|
||||
size_t len);
|
||||
|
||||
/**
|
||||
* crypto_public_key_encrypt_pkcs1_v15 - Public key encryption (PKCS #1 v1.5)
|
||||
* @key: Public key
|
||||
* @in: Plaintext buffer
|
||||
* @inlen: Length of plaintext buffer in bytes
|
||||
* @out: Output buffer for encrypted data
|
||||
* @outlen: Length of output buffer in bytes; set to used length on success
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*
|
||||
* This function is only used with internal TLSv1 implementation
|
||||
* (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
|
||||
* to implement this.
|
||||
*/
|
||||
int __must_check crypto_public_key_encrypt_pkcs1_v15(
|
||||
struct crypto_public_key *key, const u8 *in, size_t inlen,
|
||||
u8 *out, size_t *outlen);
|
||||
|
||||
/**
|
||||
* crypto_private_key_decrypt_pkcs1_v15 - Private key decryption (PKCS #1 v1.5)
|
||||
* @key: Private key
|
||||
* @in: Encrypted buffer
|
||||
* @inlen: Length of encrypted buffer in bytes
|
||||
* @out: Output buffer for encrypted data
|
||||
* @outlen: Length of output buffer in bytes; set to used length on success
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*
|
||||
* This function is only used with internal TLSv1 implementation
|
||||
* (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
|
||||
* to implement this.
|
||||
*/
|
||||
int __must_check crypto_private_key_decrypt_pkcs1_v15(
|
||||
struct crypto_private_key *key, const u8 *in, size_t inlen,
|
||||
u8 *out, size_t *outlen);
|
||||
|
||||
/**
|
||||
* crypto_private_key_sign_pkcs1 - Sign with private key (PKCS #1)
|
||||
* @key: Private key from crypto_private_key_import()
|
||||
* @in: Plaintext buffer
|
||||
* @inlen: Length of plaintext buffer in bytes
|
||||
* @out: Output buffer for encrypted (signed) data
|
||||
* @outlen: Length of output buffer in bytes; set to used length on success
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*
|
||||
* This function is only used with internal TLSv1 implementation
|
||||
* (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
|
||||
* to implement this.
|
||||
*/
|
||||
int __must_check crypto_private_key_sign_pkcs1(struct crypto_private_key *key,
|
||||
const u8 *in, size_t inlen,
|
||||
u8 *out, size_t *outlen);
|
||||
|
||||
/**
|
||||
* crypto_public_key_free - Free public key
|
||||
* @key: Public key
|
||||
*
|
||||
* This function is only used with internal TLSv1 implementation
|
||||
* (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
|
||||
* to implement this.
|
||||
*/
|
||||
void crypto_public_key_free(struct crypto_public_key *key);
|
||||
|
||||
/**
|
||||
* crypto_private_key_free - Free private key
|
||||
* @key: Private key from crypto_private_key_import()
|
||||
*
|
||||
* This function is only used with internal TLSv1 implementation
|
||||
* (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
|
||||
* to implement this.
|
||||
*/
|
||||
void crypto_private_key_free(struct crypto_private_key *key);
|
||||
|
||||
/**
|
||||
* crypto_public_key_decrypt_pkcs1 - Decrypt PKCS #1 signature
|
||||
* @key: Public key
|
||||
* @crypt: Encrypted signature data (using the private key)
|
||||
* @crypt_len: Encrypted signature data length
|
||||
* @plain: Buffer for plaintext (at least crypt_len bytes)
|
||||
* @plain_len: Plaintext length (max buffer size on input, real len on output);
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int __must_check crypto_public_key_decrypt_pkcs1(
|
||||
struct crypto_public_key *key, const u8 *crypt, size_t crypt_len,
|
||||
u8 *plain, size_t *plain_len);
|
||||
|
||||
/**
|
||||
* crypto_global_init - Initialize crypto wrapper
|
||||
*
|
||||
* This function is only used with internal TLSv1 implementation
|
||||
* (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
|
||||
* to implement this.
|
||||
*/
|
||||
int __must_check crypto_global_init(void);
|
||||
|
||||
/**
|
||||
* crypto_global_deinit - Deinitialize crypto wrapper
|
||||
*
|
||||
* This function is only used with internal TLSv1 implementation
|
||||
* (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
|
||||
* to implement this.
|
||||
*/
|
||||
void crypto_global_deinit(void);
|
||||
|
||||
/**
|
||||
* crypto_mod_exp - Modular exponentiation of large integers
|
||||
* @base: Base integer (big endian byte array)
|
||||
* @base_len: Length of base integer in bytes
|
||||
* @power: Power integer (big endian byte array)
|
||||
* @power_len: Length of power integer in bytes
|
||||
* @modulus: Modulus integer (big endian byte array)
|
||||
* @modulus_len: Length of modulus integer in bytes
|
||||
* @result: Buffer for the result
|
||||
* @result_len: Result length (max buffer size on input, real len on output)
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*
|
||||
* This function calculates result = base ^ power mod modulus. modules_len is
|
||||
* used as the maximum size of modulus buffer. It is set to the used size on
|
||||
* success.
|
||||
*
|
||||
* This function is only used with internal TLSv1 implementation
|
||||
* (CONFIG_TLS=internal). If that is not used, the crypto wrapper does not need
|
||||
* to implement this.
|
||||
*/
|
||||
int __must_check crypto_mod_exp(const u8 *base, size_t base_len,
|
||||
const u8 *power, size_t power_len,
|
||||
const u8 *modulus, size_t modulus_len,
|
||||
u8 *result, size_t *result_len);
|
||||
|
||||
/**
|
||||
* rc4_skip - XOR RC4 stream to given data with skip-stream-start
|
||||
* @key: RC4 key
|
||||
* @keylen: RC4 key length
|
||||
* @skip: number of bytes to skip from the beginning of the RC4 stream
|
||||
* @data: data to be XOR'ed with RC4 stream
|
||||
* @data_len: buf length
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*
|
||||
* Generate RC4 pseudo random stream for the given key, skip beginning of the
|
||||
* stream, and XOR the end result with the data buffer to perform RC4
|
||||
* encryption/decryption.
|
||||
*/
|
||||
int rc4_skip(const u8 *key, size_t keylen, size_t skip,
|
||||
u8 *data, size_t data_len);
|
||||
|
||||
#endif /* CRYPTO_H */
|
|
@ -0,0 +1,307 @@
|
|||
/*
|
||||
* SHA1 hash implementation and interface functions
|
||||
* Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
|
||||
#include "common.h"
|
||||
#include "sha1.h"
|
||||
#include "sha1_i.h"
|
||||
//#include "md5.h"
|
||||
#include "crypto.h"
|
||||
|
||||
typedef struct SHA1Context SHA1_CTX;
|
||||
|
||||
void SHA1Transform(u32 state[5], const unsigned char buffer[64]);
|
||||
|
||||
|
||||
/**
|
||||
* sha1_vector - SHA-1 hash for data vector
|
||||
* @num_elem: Number of elements in the data vector
|
||||
* @addr: Pointers to the data areas
|
||||
* @len: Lengths of the data blocks
|
||||
* @mac: Buffer for the hash
|
||||
* Returns: 0 on success, -1 of failure
|
||||
*/
|
||||
int sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac)
|
||||
{
|
||||
SHA1_CTX ctx;
|
||||
size_t i;
|
||||
|
||||
SHA1Init(&ctx);
|
||||
for (i = 0; i < num_elem; i++)
|
||||
SHA1Update(&ctx, addr[i], len[i]);
|
||||
SHA1Final(mac, &ctx);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* ===== start - public domain SHA1 implementation ===== */
|
||||
|
||||
/*
|
||||
SHA-1 in C
|
||||
By Steve Reid <sreid@sea-to-sky.net>
|
||||
100% Public Domain
|
||||
|
||||
-----------------
|
||||
Modified 7/98
|
||||
By James H. Brown <jbrown@burgoyne.com>
|
||||
Still 100% Public Domain
|
||||
|
||||
Corrected a problem which generated improper hash values on 16 bit machines
|
||||
Routine SHA1Update changed from
|
||||
void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int
|
||||
len)
|
||||
to
|
||||
void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned
|
||||
long len)
|
||||
|
||||
The 'len' parameter was declared an int which works fine on 32 bit machines.
|
||||
However, on 16 bit machines an int is too small for the shifts being done
|
||||
against
|
||||
it. This caused the hash function to generate incorrect values if len was
|
||||
greater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update().
|
||||
|
||||
Since the file IO in main() reads 16K at a time, any file 8K or larger would
|
||||
be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million
|
||||
"a"s).
|
||||
|
||||
I also changed the declaration of variables i & j in SHA1Update to
|
||||
unsigned long from unsigned int for the same reason.
|
||||
|
||||
These changes should make no difference to any 32 bit implementations since
|
||||
an
|
||||
int and a long are the same size in those environments.
|
||||
|
||||
--
|
||||
I also corrected a few compiler warnings generated by Borland C.
|
||||
1. Added #include <process.h> for exit() prototype
|
||||
2. Removed unused variable 'j' in SHA1Final
|
||||
3. Changed exit(0) to return(0) at end of main.
|
||||
|
||||
ALL changes I made can be located by searching for comments containing 'JHB'
|
||||
-----------------
|
||||
Modified 8/98
|
||||
By Steve Reid <sreid@sea-to-sky.net>
|
||||
Still 100% public domain
|
||||
|
||||
1- Removed #include <process.h> and used return() instead of exit()
|
||||
2- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall)
|
||||
3- Changed email address from steve@edmweb.com to sreid@sea-to-sky.net
|
||||
|
||||
-----------------
|
||||
Modified 4/01
|
||||
By Saul Kravitz <Saul.Kravitz@celera.com>
|
||||
Still 100% PD
|
||||
Modified to run on Compaq Alpha hardware.
|
||||
|
||||
-----------------
|
||||
Modified 4/01
|
||||
By Jouni Malinen <j@w1.fi>
|
||||
Minor changes to match the coding style used in Dynamics.
|
||||
|
||||
Modified September 24, 2004
|
||||
By Jouni Malinen <j@w1.fi>
|
||||
Fixed alignment issue in SHA1Transform when SHA1HANDSOFF is defined.
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
Test Vectors (from FIPS PUB 180-1)
|
||||
"abc"
|
||||
A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
|
||||
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
|
||||
84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
|
||||
A million repetitions of "a"
|
||||
34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
|
||||
*/
|
||||
|
||||
#define SHA1HANDSOFF
|
||||
|
||||
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
|
||||
|
||||
/* blk0() and blk() perform the initial expand. */
|
||||
/* I got the idea of expanding during the round function from SSLeay */
|
||||
#ifndef WORDS_BIGENDIAN
|
||||
#define blk0(i) (block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) | \
|
||||
(rol(block->l[i], 8) & 0x00FF00FF))
|
||||
#else
|
||||
#define blk0(i) block->l[i]
|
||||
#endif
|
||||
#define blk(i) (block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ \
|
||||
block->l[(i + 8) & 15] ^ block->l[(i + 2) & 15] ^ block->l[i & 15], 1))
|
||||
|
||||
/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
|
||||
#define R0(v,w,x,y,z,i) \
|
||||
z += ((w & (x ^ y)) ^ y) + blk0(i) + 0x5A827999 + rol(v, 5); \
|
||||
w = rol(w, 30);
|
||||
#define R1(v,w,x,y,z,i) \
|
||||
z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \
|
||||
w = rol(w, 30);
|
||||
#define R2(v,w,x,y,z,i) \
|
||||
z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); w = rol(w, 30);
|
||||
#define R3(v,w,x,y,z,i) \
|
||||
z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \
|
||||
w = rol(w, 30);
|
||||
#define R4(v,w,x,y,z,i) \
|
||||
z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \
|
||||
w=rol(w, 30);
|
||||
|
||||
|
||||
#ifdef VERBOSE /* SAK */
|
||||
void SHAPrintContext(SHA1_CTX *context, char *msg)
|
||||
{
|
||||
printf("%s (%d,%d) %x %x %x %x %x\n",
|
||||
msg,
|
||||
context->count[0], context->count[1],
|
||||
context->state[0],
|
||||
context->state[1],
|
||||
context->state[2],
|
||||
context->state[3],
|
||||
context->state[4]);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Hash a single 512-bit block. This is the core of the algorithm. */
|
||||
|
||||
void SHA1Transform(u32 state[5], const unsigned char buffer[64])
|
||||
{
|
||||
u32 a, b, c, d, e;
|
||||
typedef union {
|
||||
unsigned char c[64];
|
||||
u32 l[16];
|
||||
} CHAR64LONG16;
|
||||
CHAR64LONG16* block;
|
||||
#ifdef SHA1HANDSOFF
|
||||
CHAR64LONG16 workspace;
|
||||
block = &workspace;
|
||||
os_memcpy(block, buffer, 64);
|
||||
#else
|
||||
block = (CHAR64LONG16 *) buffer;
|
||||
#endif
|
||||
/* Copy context->state[] to working vars */
|
||||
a = state[0];
|
||||
b = state[1];
|
||||
c = state[2];
|
||||
d = state[3];
|
||||
e = state[4];
|
||||
/* 4 rounds of 20 operations each. Loop unrolled. */
|
||||
R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
|
||||
R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
|
||||
R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
|
||||
R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
|
||||
R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
|
||||
R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
|
||||
R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
|
||||
R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
|
||||
R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
|
||||
R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
|
||||
R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
|
||||
R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
|
||||
R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
|
||||
R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
|
||||
R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
|
||||
R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
|
||||
R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
|
||||
R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
|
||||
R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
|
||||
R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
|
||||
/* Add the working vars back into context.state[] */
|
||||
state[0] += a;
|
||||
state[1] += b;
|
||||
state[2] += c;
|
||||
state[3] += d;
|
||||
state[4] += e;
|
||||
/* Wipe variables */
|
||||
a = b = c = d = e = 0;
|
||||
#ifdef SHA1HANDSOFF
|
||||
os_memset(block, 0, 64);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* SHA1Init - Initialize new context */
|
||||
|
||||
void SHA1Init(SHA1_CTX* context)
|
||||
{
|
||||
/* SHA1 initialization constants */
|
||||
context->state[0] = 0x67452301;
|
||||
context->state[1] = 0xEFCDAB89;
|
||||
context->state[2] = 0x98BADCFE;
|
||||
context->state[3] = 0x10325476;
|
||||
context->state[4] = 0xC3D2E1F0;
|
||||
context->count[0] = context->count[1] = 0;
|
||||
}
|
||||
|
||||
|
||||
/* Run your data through this. */
|
||||
|
||||
void SHA1Update(SHA1_CTX* context, const void *_data, u32 len)
|
||||
{
|
||||
u32 i, j;
|
||||
const unsigned char *data = _data;
|
||||
|
||||
#ifdef VERBOSE
|
||||
SHAPrintContext(context, "before");
|
||||
#endif
|
||||
j = (context->count[0] >> 3) & 63;
|
||||
if ((context->count[0] += len << 3) < (len << 3))
|
||||
context->count[1]++;
|
||||
context->count[1] += (len >> 29);
|
||||
if ((j + len) > 63) {
|
||||
os_memcpy(&context->buffer[j], data, (i = 64-j));
|
||||
SHA1Transform(context->state, context->buffer);
|
||||
for ( ; i + 63 < len; i += 64) {
|
||||
SHA1Transform(context->state, &data[i]);
|
||||
}
|
||||
j = 0;
|
||||
}
|
||||
else i = 0;
|
||||
os_memcpy(&context->buffer[j], &data[i], len - i);
|
||||
#ifdef VERBOSE
|
||||
SHAPrintContext(context, "after ");
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* Add padding and return the message digest. */
|
||||
|
||||
void SHA1Final(unsigned char digest[20], SHA1_CTX* context)
|
||||
{
|
||||
u32 i;
|
||||
unsigned char finalcount[8];
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
finalcount[i] = (unsigned char)
|
||||
((context->count[(i >= 4 ? 0 : 1)] >>
|
||||
((3-(i & 3)) * 8) ) & 255); /* Endian independent */
|
||||
}
|
||||
SHA1Update(context, (unsigned char *) "\200", 1);
|
||||
while ((context->count[0] & 504) != 448) {
|
||||
SHA1Update(context, (unsigned char *) "\0", 1);
|
||||
}
|
||||
SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform()
|
||||
*/
|
||||
for (i = 0; i < 20; i++) {
|
||||
digest[i] = (unsigned char)
|
||||
((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) &
|
||||
255);
|
||||
}
|
||||
/* Wipe variables */
|
||||
i = 0;
|
||||
os_memset(context->buffer, 0, 64);
|
||||
os_memset(context->state, 0, 20);
|
||||
os_memset(context->count, 0, 8);
|
||||
os_memset(finalcount, 0, 8);
|
||||
}
|
||||
|
||||
/* ===== end - public domain SHA1 implementation ===== */
|
|
@ -0,0 +1,162 @@
|
|||
/*
|
||||
* SHA1 hash implementation and interface functions
|
||||
* Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
|
||||
#include "common.h"
|
||||
#include "sha1.h"
|
||||
#include "crypto.h"
|
||||
|
||||
|
||||
/**
|
||||
* hmac_sha1_vector - HMAC-SHA1 over data vector (RFC 2104)
|
||||
* @key: Key for HMAC operations
|
||||
* @key_len: Length of the key in bytes
|
||||
* @num_elem: Number of elements in the data vector
|
||||
* @addr: Pointers to the data areas
|
||||
* @len: Lengths of the data blocks
|
||||
* @mac: Buffer for the hash (20 bytes)
|
||||
* Returns: 0 on success, -1 on failure
|
||||
*/
|
||||
int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem,
|
||||
const u8 *addr[], const size_t *len, u8 *mac)
|
||||
{
|
||||
unsigned char k_pad[64]; /* padding - key XORd with ipad/opad */
|
||||
unsigned char tk[20];
|
||||
const u8 *_addr[6];
|
||||
size_t _len[6], i;
|
||||
|
||||
if (num_elem > 5) {
|
||||
/*
|
||||
* Fixed limit on the number of fragments to avoid having to
|
||||
* allocate memory (which could fail).
|
||||
*/
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* if key is longer than 64 bytes reset it to key = SHA1(key) */
|
||||
if (key_len > 64) {
|
||||
if (sha1_vector(1, &key, &key_len, tk))
|
||||
return -1;
|
||||
key = tk;
|
||||
key_len = 20;
|
||||
}
|
||||
|
||||
/* the HMAC_SHA1 transform looks like:
|
||||
*
|
||||
* SHA1(K XOR opad, SHA1(K XOR ipad, text))
|
||||
*
|
||||
* where K is an n byte key
|
||||
* ipad is the byte 0x36 repeated 64 times
|
||||
* opad is the byte 0x5c repeated 64 times
|
||||
* and text is the data being protected */
|
||||
|
||||
/* start out by storing key in ipad */
|
||||
os_memset(k_pad, 0, sizeof(k_pad));
|
||||
os_memcpy(k_pad, key, key_len);
|
||||
/* XOR key with ipad values */
|
||||
for (i = 0; i < 64; i++)
|
||||
k_pad[i] ^= 0x36;
|
||||
|
||||
/* perform inner SHA1 */
|
||||
_addr[0] = k_pad;
|
||||
_len[0] = 64;
|
||||
for (i = 0; i < num_elem; i++) {
|
||||
_addr[i + 1] = addr[i];
|
||||
_len[i + 1] = len[i];
|
||||
}
|
||||
if (sha1_vector(1 + num_elem, _addr, _len, mac))
|
||||
return -1;
|
||||
|
||||
os_memset(k_pad, 0, sizeof(k_pad));
|
||||
os_memcpy(k_pad, key, key_len);
|
||||
/* XOR key with opad values */
|
||||
for (i = 0; i < 64; i++)
|
||||
k_pad[i] ^= 0x5c;
|
||||
|
||||
/* perform outer SHA1 */
|
||||
_addr[0] = k_pad;
|
||||
_len[0] = 64;
|
||||
_addr[1] = mac;
|
||||
_len[1] = SHA1_MAC_LEN;
|
||||
return sha1_vector(2, _addr, _len, mac);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* hmac_sha1 - HMAC-SHA1 over data buffer (RFC 2104)
|
||||
* @key: Key for HMAC operations
|
||||
* @key_len: Length of the key in bytes
|
||||
* @data: Pointers to the data area
|
||||
* @data_len: Length of the data area
|
||||
* @mac: Buffer for the hash (20 bytes)
|
||||
* Returns: 0 on success, -1 of failure
|
||||
*/
|
||||
int hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
|
||||
u8 *mac)
|
||||
{
|
||||
return hmac_sha1_vector(key, key_len, 1, &data, &data_len, mac);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* sha1_prf - SHA1-based Pseudo-Random Function (PRF) (IEEE 802.11i, 8.5.1.1)
|
||||
* @key: Key for PRF
|
||||
* @key_len: Length of the key in bytes
|
||||
* @label: A unique label for each purpose of the PRF
|
||||
* @data: Extra data to bind into the key
|
||||
* @data_len: Length of the data
|
||||
* @buf: Buffer for the generated pseudo-random key
|
||||
* @buf_len: Number of bytes of key to generate
|
||||
* Returns: 0 on success, -1 of failure
|
||||
*
|
||||
* This function is used to derive new, cryptographically separate keys from a
|
||||
* given key (e.g., PMK in IEEE 802.11i).
|
||||
*/
|
||||
int sha1_prf(const u8 *key, size_t key_len, const char *label,
|
||||
const u8 *data, size_t data_len, u8 *buf, size_t buf_len)
|
||||
{
|
||||
u8 counter = 0;
|
||||
size_t pos, plen;
|
||||
u8 hash[SHA1_MAC_LEN];
|
||||
size_t label_len = os_strlen(label) + 1;
|
||||
const unsigned char *addr[3];
|
||||
size_t len[3];
|
||||
|
||||
addr[0] = (u8 *) label;
|
||||
len[0] = label_len;
|
||||
addr[1] = data;
|
||||
len[1] = data_len;
|
||||
addr[2] = &counter;
|
||||
len[2] = 1;
|
||||
|
||||
pos = 0;
|
||||
while (pos < buf_len) {
|
||||
plen = buf_len - pos;
|
||||
if (plen >= SHA1_MAC_LEN) {
|
||||
if (hmac_sha1_vector(key, key_len, 3, addr, len,
|
||||
&buf[pos]))
|
||||
return -1;
|
||||
pos += SHA1_MAC_LEN;
|
||||
} else {
|
||||
if (hmac_sha1_vector(key, key_len, 3, addr, len,
|
||||
hash))
|
||||
return -1;
|
||||
os_memcpy(&buf[pos], hash, plen);
|
||||
break;
|
||||
}
|
||||
counter++;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
|
@ -0,0 +1,33 @@
|
|||
/*
|
||||
* SHA1 hash implementation and interface functions
|
||||
* Copyright (c) 2003-2009, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#ifndef SHA1_H
|
||||
#define SHA1_H
|
||||
|
||||
#define SHA1_MAC_LEN 20
|
||||
|
||||
int hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem,
|
||||
const u8 *addr[], const size_t *len, u8 *mac);
|
||||
int hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
|
||||
u8 *mac);
|
||||
int sha1_prf(const u8 *key, size_t key_len, const char *label,
|
||||
const u8 *data, size_t data_len, u8 *buf, size_t buf_len);
|
||||
int sha1_t_prf(const u8 *key, size_t key_len, const char *label,
|
||||
const u8 *seed, size_t seed_len, u8 *buf, size_t buf_len);
|
||||
int __must_check tls_prf_sha1_md5(const u8 *secret, size_t secret_len,
|
||||
const char *label, const u8 *seed,
|
||||
size_t seed_len, u8 *out, size_t outlen);
|
||||
int pbkdf2_sha1(const char *passphrase, const char *ssid, size_t ssid_len,
|
||||
int iterations, u8 *buf, size_t buflen);
|
||||
#endif /* SHA1_H */
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
* SHA1 internal definitions
|
||||
* Copyright (c) 2003-2005, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#ifndef SHA1_I_H
|
||||
#define SHA1_I_H
|
||||
|
||||
struct SHA1Context {
|
||||
u32 state[5];
|
||||
u32 count[2];
|
||||
unsigned char buffer[64];
|
||||
};
|
||||
|
||||
void SHA1Init(struct SHA1Context *context);
|
||||
void SHA1Update(struct SHA1Context *context, const void *data, u32 len);
|
||||
void SHA1Final(unsigned char digest[20], struct SHA1Context *context);
|
||||
void SHA1Transform(u32 state[5], const unsigned char buffer[64]);
|
||||
|
||||
#endif /* SHA1_I_H */
|
|
@ -0,0 +1,231 @@
|
|||
/*
|
||||
* SHA-256 hash implementation and interface functions
|
||||
* Copyright (c) 2003-2011, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
|
||||
#include "common.h"
|
||||
#include "sha256.h"
|
||||
#include "sha256_i.h"
|
||||
#include "crypto.h"
|
||||
|
||||
|
||||
/**
|
||||
* sha256_vector - SHA256 hash for data vector
|
||||
* @num_elem: Number of elements in the data vector
|
||||
* @addr: Pointers to the data areas
|
||||
* @len: Lengths of the data blocks
|
||||
* @mac: Buffer for the hash
|
||||
* Returns: 0 on success, -1 of failure
|
||||
*/
|
||||
int sha256_vector(size_t num_elem, const u8 *addr[], const size_t *len,
|
||||
u8 *mac)
|
||||
{
|
||||
struct sha256_state ctx;
|
||||
size_t i;
|
||||
|
||||
sha256_init(&ctx);
|
||||
for (i = 0; i < num_elem; i++)
|
||||
if (sha256_process(&ctx, addr[i], len[i]))
|
||||
return -1;
|
||||
if (sha256_done(&ctx, mac))
|
||||
return -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* ===== start - public domain SHA256 implementation ===== */
|
||||
|
||||
/* This is based on SHA256 implementation in LibTomCrypt that was released into
|
||||
* public domain by Tom St Denis. */
|
||||
|
||||
/* the K array */
|
||||
static const unsigned long K[64] = {
|
||||
0x428a2f98UL, 0x71374491UL, 0xb5c0fbcfUL, 0xe9b5dba5UL, 0x3956c25bUL,
|
||||
0x59f111f1UL, 0x923f82a4UL, 0xab1c5ed5UL, 0xd807aa98UL, 0x12835b01UL,
|
||||
0x243185beUL, 0x550c7dc3UL, 0x72be5d74UL, 0x80deb1feUL, 0x9bdc06a7UL,
|
||||
0xc19bf174UL, 0xe49b69c1UL, 0xefbe4786UL, 0x0fc19dc6UL, 0x240ca1ccUL,
|
||||
0x2de92c6fUL, 0x4a7484aaUL, 0x5cb0a9dcUL, 0x76f988daUL, 0x983e5152UL,
|
||||
0xa831c66dUL, 0xb00327c8UL, 0xbf597fc7UL, 0xc6e00bf3UL, 0xd5a79147UL,
|
||||
0x06ca6351UL, 0x14292967UL, 0x27b70a85UL, 0x2e1b2138UL, 0x4d2c6dfcUL,
|
||||
0x53380d13UL, 0x650a7354UL, 0x766a0abbUL, 0x81c2c92eUL, 0x92722c85UL,
|
||||
0xa2bfe8a1UL, 0xa81a664bUL, 0xc24b8b70UL, 0xc76c51a3UL, 0xd192e819UL,
|
||||
0xd6990624UL, 0xf40e3585UL, 0x106aa070UL, 0x19a4c116UL, 0x1e376c08UL,
|
||||
0x2748774cUL, 0x34b0bcb5UL, 0x391c0cb3UL, 0x4ed8aa4aUL, 0x5b9cca4fUL,
|
||||
0x682e6ff3UL, 0x748f82eeUL, 0x78a5636fUL, 0x84c87814UL, 0x8cc70208UL,
|
||||
0x90befffaUL, 0xa4506cebUL, 0xbef9a3f7UL, 0xc67178f2UL
|
||||
};
|
||||
|
||||
|
||||
/* Various logical functions */
|
||||
#define RORc(x, y) \
|
||||
( ((((unsigned long) (x) & 0xFFFFFFFFUL) >> (unsigned long) ((y) & 31)) | \
|
||||
((unsigned long) (x) << (unsigned long) (32 - ((y) & 31)))) & 0xFFFFFFFFUL)
|
||||
#define Ch(x,y,z) (z ^ (x & (y ^ z)))
|
||||
#define Maj(x,y,z) (((x | y) & z) | (x & y))
|
||||
#define S(x, n) RORc((x), (n))
|
||||
#define R(x, n) (((x)&0xFFFFFFFFUL)>>(n))
|
||||
#define Sigma0(x) (S(x, 2) ^ S(x, 13) ^ S(x, 22))
|
||||
#define Sigma1(x) (S(x, 6) ^ S(x, 11) ^ S(x, 25))
|
||||
#define Gamma0(x) (S(x, 7) ^ S(x, 18) ^ R(x, 3))
|
||||
#define Gamma1(x) (S(x, 17) ^ S(x, 19) ^ R(x, 10))
|
||||
#ifndef MIN
|
||||
#define MIN(x, y) (((x) < (y)) ? (x) : (y))
|
||||
#endif
|
||||
|
||||
/* compress 512-bits */
|
||||
static int sha256_compress(struct sha256_state *md, unsigned char *buf)
|
||||
{
|
||||
u32 S[8], W[64], t0, t1;
|
||||
u32 t;
|
||||
int i;
|
||||
|
||||
/* copy state into S */
|
||||
for (i = 0; i < 8; i++) {
|
||||
S[i] = md->state[i];
|
||||
}
|
||||
|
||||
/* copy the state into 512-bits into W[0..15] */
|
||||
for (i = 0; i < 16; i++)
|
||||
W[i] = WPA_GET_BE32(buf + (4 * i));
|
||||
|
||||
/* fill W[16..63] */
|
||||
for (i = 16; i < 64; i++) {
|
||||
W[i] = Gamma1(W[i - 2]) + W[i - 7] + Gamma0(W[i - 15]) +
|
||||
W[i - 16];
|
||||
}
|
||||
|
||||
/* Compress */
|
||||
#define RND(a,b,c,d,e,f,g,h,i) \
|
||||
t0 = h + Sigma1(e) + Ch(e, f, g) + K[i] + W[i]; \
|
||||
t1 = Sigma0(a) + Maj(a, b, c); \
|
||||
d += t0; \
|
||||
h = t0 + t1;
|
||||
|
||||
for (i = 0; i < 64; ++i) {
|
||||
RND(S[0], S[1], S[2], S[3], S[4], S[5], S[6], S[7], i);
|
||||
t = S[7]; S[7] = S[6]; S[6] = S[5]; S[5] = S[4];
|
||||
S[4] = S[3]; S[3] = S[2]; S[2] = S[1]; S[1] = S[0]; S[0] = t;
|
||||
}
|
||||
|
||||
/* feedback */
|
||||
for (i = 0; i < 8; i++) {
|
||||
md->state[i] = md->state[i] + S[i];
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* Initialize the hash state */
|
||||
void sha256_init(struct sha256_state *md)
|
||||
{
|
||||
md->curlen = 0;
|
||||
md->length = 0;
|
||||
md->state[0] = 0x6A09E667UL;
|
||||
md->state[1] = 0xBB67AE85UL;
|
||||
md->state[2] = 0x3C6EF372UL;
|
||||
md->state[3] = 0xA54FF53AUL;
|
||||
md->state[4] = 0x510E527FUL;
|
||||
md->state[5] = 0x9B05688CUL;
|
||||
md->state[6] = 0x1F83D9ABUL;
|
||||
md->state[7] = 0x5BE0CD19UL;
|
||||
}
|
||||
|
||||
/**
|
||||
Process a block of memory though the hash
|
||||
@param md The hash state
|
||||
@param in The data to hash
|
||||
@param inlen The length of the data (octets)
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int sha256_process(struct sha256_state *md, const unsigned char *in,
|
||||
unsigned long inlen)
|
||||
{
|
||||
unsigned long n;
|
||||
|
||||
if (md->curlen >= sizeof(md->buf))
|
||||
return -1;
|
||||
|
||||
while (inlen > 0) {
|
||||
if (md->curlen == 0 && inlen >= SHA256_BLOCK_SIZE) {
|
||||
if (sha256_compress(md, (unsigned char *) in) < 0)
|
||||
return -1;
|
||||
md->length += SHA256_BLOCK_SIZE * 8;
|
||||
in += SHA256_BLOCK_SIZE;
|
||||
inlen -= SHA256_BLOCK_SIZE;
|
||||
} else {
|
||||
n = MIN(inlen, (SHA256_BLOCK_SIZE - md->curlen));
|
||||
os_memcpy(md->buf + md->curlen, in, n);
|
||||
md->curlen += n;
|
||||
in += n;
|
||||
inlen -= n;
|
||||
if (md->curlen == SHA256_BLOCK_SIZE) {
|
||||
if (sha256_compress(md, md->buf) < 0)
|
||||
return -1;
|
||||
md->length += 8 * SHA256_BLOCK_SIZE;
|
||||
md->curlen = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Terminate the hash to get the digest
|
||||
@param md The hash state
|
||||
@param out [out] The destination of the hash (32 bytes)
|
||||
@return CRYPT_OK if successful
|
||||
*/
|
||||
int sha256_done(struct sha256_state *md, unsigned char *out)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (md->curlen >= sizeof(md->buf))
|
||||
return -1;
|
||||
|
||||
/* increase the length of the message */
|
||||
md->length += md->curlen * 8;
|
||||
|
||||
/* append the '1' bit */
|
||||
md->buf[md->curlen++] = (unsigned char) 0x80;
|
||||
|
||||
/* if the length is currently above 56 bytes we append zeros
|
||||
* then compress. Then we can fall back to padding zeros and length
|
||||
* encoding like normal.
|
||||
*/
|
||||
if (md->curlen > 56) {
|
||||
while (md->curlen < SHA256_BLOCK_SIZE) {
|
||||
md->buf[md->curlen++] = (unsigned char) 0;
|
||||
}
|
||||
sha256_compress(md, md->buf);
|
||||
md->curlen = 0;
|
||||
}
|
||||
|
||||
/* pad up to 56 bytes of zeroes */
|
||||
while (md->curlen < 56) {
|
||||
md->buf[md->curlen++] = (unsigned char) 0;
|
||||
}
|
||||
|
||||
/* store length */
|
||||
WPA_PUT_BE64(md->buf + 56, md->length);
|
||||
sha256_compress(md, md->buf);
|
||||
|
||||
/* copy output */
|
||||
for (i = 0; i < 8; i++)
|
||||
WPA_PUT_BE32(out + (4 * i), md->state[i]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* ===== end - public domain SHA256 implementation ===== */
|
|
@ -0,0 +1,156 @@
|
|||
/*
|
||||
* SHA-256 hash implementation and interface functions
|
||||
* Copyright (c) 2003-2007, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
|
||||
#include "common.h"
|
||||
#include "sha256.h"
|
||||
#include "crypto.h"
|
||||
|
||||
|
||||
/**
|
||||
* hmac_sha256_vector - HMAC-SHA256 over data vector (RFC 2104)
|
||||
* @key: Key for HMAC operations
|
||||
* @key_len: Length of the key in bytes
|
||||
* @num_elem: Number of elements in the data vector
|
||||
* @addr: Pointers to the data areas
|
||||
* @len: Lengths of the data blocks
|
||||
* @mac: Buffer for the hash (32 bytes)
|
||||
*/
|
||||
void hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem,
|
||||
const u8 *addr[], const size_t *len, u8 *mac)
|
||||
{
|
||||
unsigned char k_pad[64]; /* padding - key XORd with ipad/opad */
|
||||
unsigned char tk[32];
|
||||
const u8 *_addr[6];
|
||||
size_t _len[6], i;
|
||||
|
||||
if (num_elem > 5) {
|
||||
/*
|
||||
* Fixed limit on the number of fragments to avoid having to
|
||||
* allocate memory (which could fail).
|
||||
*/
|
||||
return;
|
||||
}
|
||||
|
||||
/* if key is longer than 64 bytes reset it to key = SHA256(key) */
|
||||
if (key_len > 64) {
|
||||
sha256_vector(1, &key, &key_len, tk);
|
||||
key = tk;
|
||||
key_len = 32;
|
||||
}
|
||||
|
||||
/* the HMAC_SHA256 transform looks like:
|
||||
*
|
||||
* SHA256(K XOR opad, SHA256(K XOR ipad, text))
|
||||
*
|
||||
* where K is an n byte key
|
||||
* ipad is the byte 0x36 repeated 64 times
|
||||
* opad is the byte 0x5c repeated 64 times
|
||||
* and text is the data being protected */
|
||||
|
||||
/* start out by storing key in ipad */
|
||||
os_memset(k_pad, 0, sizeof(k_pad));
|
||||
os_memcpy(k_pad, key, key_len);
|
||||
/* XOR key with ipad values */
|
||||
for (i = 0; i < 64; i++)
|
||||
k_pad[i] ^= 0x36;
|
||||
|
||||
/* perform inner SHA256 */
|
||||
_addr[0] = k_pad;
|
||||
_len[0] = 64;
|
||||
for (i = 0; i < num_elem; i++) {
|
||||
_addr[i + 1] = addr[i];
|
||||
_len[i + 1] = len[i];
|
||||
}
|
||||
sha256_vector(1 + num_elem, _addr, _len, mac);
|
||||
|
||||
os_memset(k_pad, 0, sizeof(k_pad));
|
||||
os_memcpy(k_pad, key, key_len);
|
||||
/* XOR key with opad values */
|
||||
for (i = 0; i < 64; i++)
|
||||
k_pad[i] ^= 0x5c;
|
||||
|
||||
/* perform outer SHA256 */
|
||||
_addr[0] = k_pad;
|
||||
_len[0] = 64;
|
||||
_addr[1] = mac;
|
||||
_len[1] = SHA256_MAC_LEN;
|
||||
sha256_vector(2, _addr, _len, mac);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* hmac_sha256 - HMAC-SHA256 over data buffer (RFC 2104)
|
||||
* @key: Key for HMAC operations
|
||||
* @key_len: Length of the key in bytes
|
||||
* @data: Pointers to the data area
|
||||
* @data_len: Length of the data area
|
||||
* @mac: Buffer for the hash (20 bytes)
|
||||
*/
|
||||
void hmac_sha256(const u8 *key, size_t key_len, const u8 *data,
|
||||
size_t data_len, u8 *mac)
|
||||
{
|
||||
hmac_sha256_vector(key, key_len, 1, &data, &data_len, mac);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* sha256_prf - SHA256-based Pseudo-Random Function (IEEE 802.11r, 8.5.1.5.2)
|
||||
* @key: Key for PRF
|
||||
* @key_len: Length of the key in bytes
|
||||
* @label: A unique label for each purpose of the PRF
|
||||
* @data: Extra data to bind into the key
|
||||
* @data_len: Length of the data
|
||||
* @buf: Buffer for the generated pseudo-random key
|
||||
* @buf_len: Number of bytes of key to generate
|
||||
*
|
||||
* This function is used to derive new, cryptographically separate keys from a
|
||||
* given key.
|
||||
*/
|
||||
void sha256_prf(const u8 *key, size_t key_len, const char *label,
|
||||
const u8 *data, size_t data_len, u8 *buf, size_t buf_len)
|
||||
{
|
||||
u16 counter = 1;
|
||||
size_t pos, plen;
|
||||
u8 hash[SHA256_MAC_LEN];
|
||||
const u8 *addr[4];
|
||||
size_t len[4];
|
||||
u8 counter_le[2], length_le[2];
|
||||
|
||||
addr[0] = counter_le;
|
||||
len[0] = 2;
|
||||
addr[1] = (u8 *) label;
|
||||
len[1] = os_strlen(label);
|
||||
addr[2] = data;
|
||||
len[2] = data_len;
|
||||
addr[3] = length_le;
|
||||
len[3] = sizeof(length_le);
|
||||
|
||||
WPA_PUT_LE16(length_le, buf_len * 8);
|
||||
pos = 0;
|
||||
while (pos < buf_len) {
|
||||
plen = buf_len - pos;
|
||||
WPA_PUT_LE16(counter_le, counter);
|
||||
if (plen >= SHA256_MAC_LEN) {
|
||||
hmac_sha256_vector(key, key_len, 4, addr, len,
|
||||
&buf[pos]);
|
||||
pos += SHA256_MAC_LEN;
|
||||
} else {
|
||||
hmac_sha256_vector(key, key_len, 4, addr, len, hash);
|
||||
os_memcpy(&buf[pos], hash, plen);
|
||||
break;
|
||||
}
|
||||
counter++;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* SHA256 hash implementation and interface functions
|
||||
* Copyright (c) 2003-2011, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#ifndef SHA256_H
|
||||
#define SHA256_H
|
||||
|
||||
#define SHA256_MAC_LEN 32
|
||||
|
||||
void hmac_sha256_vector(const u8 *key, size_t key_len, size_t num_elem,
|
||||
const u8 *addr[], const size_t *len, u8 *mac);
|
||||
void hmac_sha256(const u8 *key, size_t key_len, const u8 *data,
|
||||
size_t data_len, u8 *mac);
|
||||
void sha256_prf(const u8 *key, size_t key_len, const char *label,
|
||||
const u8 *data, size_t data_len, u8 *buf, size_t buf_len);
|
||||
void tls_prf_sha256(const u8 *secret, size_t secret_len,
|
||||
const char *label, const u8 *seed, size_t seed_len,
|
||||
u8 *out, size_t outlen);
|
||||
|
||||
#endif /* SHA256_H */
|
|
@ -0,0 +1,31 @@
|
|||
/*
|
||||
* SHA-256 internal definitions
|
||||
* Copyright (c) 2003-2011, Jouni Malinen <j@w1.fi>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License version 2 as
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
* Alternatively, this software may be distributed under the terms of BSD
|
||||
* license.
|
||||
*
|
||||
* See README and COPYING for more details.
|
||||
*/
|
||||
|
||||
#ifndef SHA256_I_H
|
||||
#define SHA256_I_H
|
||||
|
||||
#define SHA256_BLOCK_SIZE 64
|
||||
|
||||
struct sha256_state {
|
||||
u64 length;
|
||||
u32 state[8], curlen;
|
||||
u8 buf[SHA256_BLOCK_SIZE];
|
||||
};
|
||||
|
||||
void sha256_init(struct sha256_state *md);
|
||||
int sha256_process(struct sha256_state *md, const unsigned char *in,
|
||||
unsigned long inlen);
|
||||
int sha256_done(struct sha256_state *md, unsigned char *out);
|
||||
|
||||
#endif /* SHA256_I_H */
|
|
@ -547,6 +547,12 @@ osmo_auth_supported;
|
|||
osmo_auth_c3;
|
||||
osmo_sub_auth_type_names;
|
||||
|
||||
osmo_kdf_kc128;
|
||||
osmo_kdf_kasme;
|
||||
osmo_kdf_enb;
|
||||
osmo_kdf_nh;
|
||||
osmo_kdf_nas;
|
||||
|
||||
osmo_rsl2sitype;
|
||||
osmo_sitype2rsl;
|
||||
|
||||
|
|
Loading…
Reference in New Issue