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.
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.
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.
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.
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.
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.
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.
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. .
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.
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.
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.
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.
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.