Key Generation Functions

Atheros applications use the SHA256 algorithm to compute unique HomePlug AV keys, including the Device Access Key (DAK), Network Membership Key (NMK) and Network Identifier (NID). The SHA256 algorithm is seeded, salted and rehashed differently for each type of HomePlug AV key. A different function is used to compute each type of HomePlug AV key but all of them call the SHA256 functions. The SHA256 algorithm returns a 256 bit (32 byte) digest but only the upper 128 bits (16 bytes) are used for HomePlug AV keys.

Example 7.3.  SHA256 Digest Computation

The following code example illustrates how to generate, rehash and print an SHA256 digest, or key, from a user-defined seed string and salt string. This logic is typical of that used to generate HomePlug AV compliant keys. See the HomePlug AV Specification for the specific rules used to generate each type of key.

#include <stdio.h>

#include "../crypt/SHA256.h"

#include "../crypt/SHA256Reset.c"
#include "../crypt/SHA256Block.c"
#include "../crypt/SHA256Write.c"
#include "../crypt/SHA256Fetch.c"

struct sha256 sha256; 
char * seed = "ForMeToKnowAndYouToFindOut"; 
char * salt = "X$z@p"; 
byte digest [SHA256_DIGEST_SIZE];
int i; 

SHA256Reset (&sha256); 
SHA256Write (&sha256, (byte *)(seed), strlen (seed)); 
SHA256Write (&sha256, (byte *)(salt), strlen (salt)); 
SHA256Fetch (&sha256, digest); 

for (i = 0; i < 999; i++)
{
	SHA256Reset (&sha256); 
	SHA256Write (&sha256, digest, sizeof (digest)); 
	SHA256Fetch (&sha256, digest); 
}
for (i = 0;  i < 16; i++)
{
	printf ("%02x", digest [i]); 
}
printf ("\n"); 

Above, we declare struct sha256 and initialize it using function SHA256Reset. We then write a user-defined seed string (or password) followed by an optional salt string to the digest using function SHA256Write. The resulting digest (or key) is obtained by calling function SHA256Fetch. Constant SHA256_DIGEST_SIZE is defined in SHA256.h. Although the digest is probably secure enough at this point, we rehash it 999 times for good measure. We then print the first 16 bytes of the result because HomePlug AV keys are always 16 bytes long.


MACPasswords

void MACPasswords(vendor,  
 device,  
 number,  
 count,  
 bunch,  
 space,  
 flags); 
uint32_tvendor;
uint32_tdevice;
uint32_tnumber;
unsigned count;
unsigned bunch;
unsigned space;
flag_t flags;
 

Print a range of device addresses and user passwords on stdout. The calling application must split the starting device address into a three-byte OUI and three-byte device number and pass them as the unsigned 32-bit integers vendor and device, respectively. Argument device is the first device number in the range and number is the final device number. Argument count is the number of uppercase letters comprising a password. Passwords contain this many letters but the letters are grouped for easy reading. Letter groups are separated by hyphens. Argument bunch defines how many letters form each group. Argument space is the character used to separate groups of letters. Argument flags enables or disables function features such as insertion of a used flag for use by the Atheros Production Test System or the omission of the device address on output. The output of this function is similar to that produced by the DB Builder utility distributed with the PTS. This function is declared in keys.h and defined in MACPasswords.c.

HPAVKeyDAK

void HPAVKeyDAK(DAK,  
 string); 
byte DAK [];
char const string;
 

Encode buffer DAK with the Device Access Key (DAK) derived from the NUL terminated string. The string is salted, hashed and re-hashed using the SHA256 algorithm. The DAK is always HPAVKEY_DAK_LEN bytes, defined in HPAVKey.h, so no length argument is needed. See the HomePlug AV Specification for more information. This function is declared in HPAVKey.h and defined in HPAVKeyDAK.c.

HPAVKeyNMK

void HPAVKeyNMK(digest,  
 string); 
byte digest [];
char const string;
 

Encode buffer NMK with the Network Membership Key (NMK) derived from the NUL terminated string. The string is salted, hashed and re-hashed using the SHA256 algorithm. The DAK is always HPAVKEY_NMK_LEN bytes, as defined in HPAVKey.h, so no length argument is needed. See the HomePlug AV Specification for more information. This function is declared in HPAVKey.h and defined in HPAVKeyNMK.c.

HPAVKeyNID

void HPAVKeyNID(NID,  
 NMK,  
 level); 
byte NID [];
byte const NMK [];
signed level;
 

Encode buffer NID with the Network Identification Key (NID) derived from the 16-byte Network Membership Key (NMK). The NMK is hashed and re-hashed using the SHA256 algorithm then encoded with the security level. The NID is always HPAVKEY_NID_LEN bytes, as defined in HPAVKey.h, so no length argument is needed. See the HomePlug AV Specification for more information. This function is declared in HPAVKey.h and defined in HPAVKeyNID.c.

HPAVKeyOut

void HPAVKeyOut(digest,  
 length,  
 phrase,  
 flags); 
byte const digest [];
size_t length;
char const * phrase;
flag_t flags;
 

Decode and print up to length bytes from buffer digest on stdout. Print NUL terminated phrase on the same line following the digest when bit HPAVKEY_VERBOSE, defined in HPAVKey.h, is set in flags. This procedure prints keys and phrases in a standard column-oriented format that other applications can easily read and use. This function is declared in HPAVKey.h and defined in HPAVKeyOut.c.

SHA256Block

void SHA256Block(sha256,  
 memory); 
struct sha256 * sha256;
void const * memory;
 

Merge 64 bytes of memory into the current SHA256 digest. This function performs the core computations required by the SHA256 algoithm. It is called by function SHA256Fetch and so there is no reason to call this function directly. The sha256 structure is defined in SHA256.h. The function is declared in SHA256.h and defined in SHA256Block.c.

SHA256Fetch

void SHA256Fetch(sha256,  
 digest); 
struct sha256 * sha256;
byte digest [];
 

Conclude SHA256 computation and transfer the result to the named 32-byte digest then flush the sha256 structure. The digest is always 32 bytes long regardless of the amount of information that has been written using function SHA256Write. The sha256 structure is defined in SHA256.h. This function is declared in SHA256.h and defined in SHA256Fetch.c.

Once this function is called, the sha256 structure is purged for security reasons. You must call SHA256Reset again before starting another hash or subsequent calls to this function or SHA256Write will have unpredictable results. .

SHA256Ident

void SHA256Ident(fd,  
 digest); 
int fd;
byte digest [];
 

Compute the SHA256 digest from the content of a file. The digest serves as the file fingerprint and can be used to identify identical content despite filename changes. File descriptor fd is the subject file which must be positioned to the start befor calling this function. Buffer digest will be written with the computed 256-digest and must be SHA256_DIGEST_SIZE bytes long, as defined in SHA256.h. This function is declared in SHA256.h and defined in SHA256Ident.c.

SHA256Match

void SHA256Match(fd,  
 digest); 
int fd;
byte const digest [];
 

Search a registry file for a known SHA256 digest. Return true on success or false on failure. File descriptor fd is the registry file which must be positioned to the start before calling this function. Buffer digest contains the known 256-bit digest and must be SHA256_DIGEST_SIZE bytes long, as defined in SHA256.h. A registry file consists of 64-digit hexadecimal strings that represent SHA256 digest values. Optional text may be appear between the digest and newline to document digest significance. This function ignores such text. This function is declared in SHA256.h and defined in SHA256Match.c.

SHA256Print

void SHA256Print(digest,  
 string); 
byte const digest [];
char const * string;
 

Print an SHA256 digest and optional string on stdout. Buffer digest must be SHA256_DIGEST_SIZE bytes long, as defined in SHA256.h, which results in 64 hexadecimal digits on output. Variable length string is NUL terminated but may be NULL. If string is not NULL and is not empty then a space is inserted between the digest and the string on output. This function may be used to print SHA256 digests and optional strings in standard format, such as a registry file. This function is declared in SHA256.h and defined in SHA256Print.c.

SHA256Reset

void SHA256Reset(sha256); 
struct sha256 * sha256;
 

Initialize a sha256 structure before computing a new SHA256 digest. This function should be called once before calling SHA256Write for the first time for a given digest. The sha256 structure is defined in SHA256.h. This function is declared in SHA256.h and defined in SHA256Reset.c.

SHA256Write

void SHA256Write(sha256,  
 memory,  
 extent); 
struct sha256 * sha256;
void const * memory;
size_t extent;
 

Writes a region of memory to the current SHA256 digest contained in an sha256 structure. An application may call this function any number of times to concatinate multiple memory regions before fetching the digest with function SHA256Fetch. The sha256 structure is defined in SHA256.h. This function is declared in SHA256.h and defined in SHA256Write.c.