Files
open-gpu-kernel-modules/src/common/inc/nvSha1.h
Andy Ritger 965db98552 515.48.07
2022-05-27 16:40:24 -07:00

391 lines
10 KiB
C

/*
* SPDX-FileCopyrightText: Copyright (c) 2007-2012 NVIDIA CORPORATION & AFFILIATES
* SPDX-License-Identifier: MIT
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
* DEALINGS IN THE SOFTWARE.
*/
/*!
* Utility header file to generate a one-way hash from an arbitrary
* byte array, using the Secure Hashing Algorithm 1 (SHA-1) as defined
* in FIPS PUB 180-1 published April 17, 1995:
*
* https://www.itl.nist.gov/fipspubs/fip180-1.htm
*
* Some common test cases (see Appendices A and B of the above document):
*
* SHA1("abc") =
* A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
*
* SHA1("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq") =
* 84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
*/
#ifndef __NV_SHA1_H__
#define __NV_SHA1_H__
#include "nvtypes.h"
/*!
* @brief Structure used by the SHA-1 functions to maintain the state of the
* calculations.
*/
typedef struct
{
NvU32 state[5];
NvU32 count;
NvU8 buffer[128];
} Sha1Context;
/*!
* @brief Pointer to a memory accessor function for use by the SHA-1 hash
* function.
*
* Due to memory constraints in some environments where this code is executed
* (e.g., the PMU/DPU), the data that needs to be processed by the SHA-1 hash
* function may not be readily available. This function is responsible for
* copying the data into a buffer to be used by the SHA-1 function.
*
* Besides, SHA1 library can be used by many different clients, so we need to
* provide the memory accessor functions which can work in client's environment.
*
* @param[out] pBuff The buffer to copy the new data to.
* @param[in] index The desired offset to begin copying from.
* @param[in] size The requested number of bytes to be copied.
* @param[in] info Pointer to the data passed into GenerateSha1 as pData.
*
* @return The actual number of bytes copied into the buffer.
*/
typedef NvU32 Sha1CopyFunc(NvU8 *pBuff, NvU32 index, NvU32 size, void *pInfo);
/*
* The following values are defined by the SHA-1 algorithm for initial values.
*/
#define SHA1_INIT_H0 0x67452301 //!< Initial H0 value
#define SHA1_INIT_H1 0xEFCDAB89 //!< Initial H1 value
#define SHA1_INIT_H2 0x98BADCFE //!< Initial H2 value
#define SHA1_INIT_H3 0x10325476 //!< Initial H3 value
#define SHA1_INIT_H4 0xC3D2E1F0 //!< Initial H4 value
/*!
* @brief Reverses the byte order of a word; that is, switching the endianness
* of the word.
*
* @param[in] a A 32-bit word
*
* @returns The 32-bit word with its byte order reversed.
*/
#define REVERSE_BYTE_ORDER(a) \
(((a) >> 24) | ((a) << 24) | (((a) >> 8) & 0xFF00) | (((a) << 8) & 0xFF0000))
/*!
* @brief Computation step as defined by SHA-1.
*
* Unlike the 64 byte buffer version outlined in the SHA-1 algorithm, this
* function uses a 128 byte buffer to minimize the calculation needed to
* index the data.
*
* @param[in,out] pState
* Pointer to State word array.
*
* @param[in] pBuffer
* Data to operate on. 128 bytes in length. No length checking is done,
* and is assumed to have been done by the calling function.
*/
static void
_sha1Transform
(
NvU32 *pState,
NvU8 *pBuffer
)
{
NvU32 a = pState[0];
NvU32 b = pState[1];
NvU32 c = pState[2];
NvU32 d = pState[3];
NvU32 e = pState[4];
NvU32 *pBuf = (NvU32 *)pBuffer;
NvU32 *p;
NvU32 i;
NvU32 j;
NvU32 k;
for (i = 0; i < 80; i++)
{
p = &pBuf[i & 0xf];
j = p[0];
if (i < 16)
{
j = REVERSE_BYTE_ORDER(j);
}
else
{
j ^= p[2] ^ p[8] ^ p[13];
j = (j << 1) + (j >> 31);
}
p[0] = p[16] = j;
if (i < 40)
{
if (i < 20)
{
k = 0x5a827999 + ((b & (c ^ d)) ^ d);
}
else
{
k = 0x6ed9eba1 + (b ^ c ^ d);
}
}
else
{
if (i < 60)
{
k = 0x8f1bbcdc + (((b | c) & d) | (b & c));
}
else
{
k = 0xca62c1d6 + (b ^ c ^ d);
}
}
j += (a << 5) + (a >> 27) + e + k;
e = d;
d = c;
c = (b << 30) + (b >> 2);
b = a;
a = j;
}
pState[0] += a;
pState[1] += b;
pState[2] += c;
pState[3] += d;
pState[4] += e;
}
/*!
* Initializes the SHA-1 context.
*
* @param[out] pContext
* Pointer to the context to initialize.
*/
static void
_sha1Initialize
(
Sha1Context *pContext
)
{
pContext->count = 0;
pContext->state[0] = SHA1_INIT_H0;
pContext->state[1] = SHA1_INIT_H1;
pContext->state[2] = SHA1_INIT_H2;
pContext->state[3] = SHA1_INIT_H3;
pContext->state[4] = SHA1_INIT_H4;
}
/*!
* @brief Divides the input buffer into multiple 64-byte buffers and computes
* the message digest for each.
*
* @param[in] pContext
* Pointer to a Sha1Context.
*
* @param[in] pData
* Pointer to the data array to compute the message digest.
*
* @param[in] len
* Size of the data.
*
* @param[in] copyFunc
* Copy routine to use.
*/
static void
_sha1Update
(
Sha1Context *pContext,
void *pData,
NvU32 len,
Sha1CopyFunc copyFunc
)
{
NvU32 buffer_offset = (pContext->count & 63);
NvU32 copy_size;
NvU32 idx = 0;
pContext->count += len;
while ((buffer_offset + len) > 63)
{
copy_size = 64 - buffer_offset;
copyFunc(&pContext->buffer[buffer_offset], idx, copy_size, pData);
_sha1Transform(pContext->state, pContext->buffer);
buffer_offset = 0;
idx += copy_size;
len -= copy_size;
}
if (len > 0)
{
copyFunc(&pContext->buffer[buffer_offset], idx, len, pData);
}
}
/*!
* @brief fill memory with zero; not all environments in which this
* code runs have memset(3).
*
* @param[out] pData
* The memory to be filled with zero
*
* @param[in] nBytes
* The number of bytes of memory to fill with zero
*/
static NV_INLINE void
_sha1MemZero
(
NvU8 *pData,
NvU32 nBytes
)
{
NvU32 i;
for (i = 0; i < nBytes; i++) {
pData[i] = 0;
}
}
/*!
* @brief Pads the message as specified by the SHA-1 algorithm and computes
* the message digest on the final message chunk(s).
*
* @param[out] pDigest
* The SHA-1 hash values.
*
* @param[in] pContext
* Pointer to a Sha1Context.
*/
static void
_sha1Final
(
NvU8 *pDigest,
Sha1Context *pContext
)
{
NvU32 i;
NvU32 bufferOffset = (pContext->count & 63);
NvU8 *pBuffer = (NvU8*)&pContext->buffer[bufferOffset];
NvU32 *pCount;
NvU32 *pDig32;
// append padding pattern to the end of input
*pBuffer++ = 0x80;
if (bufferOffset < 56)
{
_sha1MemZero(pBuffer, 59 - bufferOffset);
}
else
{
// need an extra sha1_transform
if (bufferOffset < 63)
{
_sha1MemZero(pBuffer, 63 - bufferOffset);
}
_sha1Transform(pContext->state, pContext->buffer);
_sha1MemZero(pContext->buffer, 60);
}
// set final count (this is the number of *bits* not *bytes*)
pCount = (NvU32*)&pContext->buffer[15 << 2];
*pCount = REVERSE_BYTE_ORDER(pContext->count << 3);
_sha1Transform(pContext->state, pContext->buffer);
// output hash with each dword in big endian
if (pDigest)
{
pDig32 = (NvU32*) pDigest;
for (i = 0; i < 5; i++)
{
pDig32[i] = REVERSE_BYTE_ORDER(pContext->state[i]);
}
}
}
/*!
* @brief Generates the SHA-1 hash value on the data provided.
*
* The function does not manipulate the source data directly, as it may not
* have direct access to it. Therefore, it relies upon the copy function to
* copy segments of the data into a local buffer before any manipulation takes
* place.
*
* @param[out] pHash
* Pointer to store the hash array. The buffer must be 20 bytes in
* length, and the result is stored in big endian format.
*
* @param[in] pData
* The source data array to transform. The actual values and make-up
* of this parameter are dependent on the copy function.
*
* @param[in] nBytes
* The size, in bytes, of the source data.
*
* @param[in] copyFunc
* The function responsible for copying data from the source
* for use by the sha1 function. It is possible for the data
* to exist outside the current execution environment (e.g.,
* the PMU, and the data to hash are in system memory), so
* the function will never directly manipulate the source
* data.
*/
#define NV_SHA1_BLOCK_LENGTH 64
#define NV_SHA1_DIGEST_LENGTH 20
static void
sha1Generate
(
NvU8 pHash[NV_SHA1_DIGEST_LENGTH],
void *pData,
NvU32 nBytes,
Sha1CopyFunc copyFunc
)
{
Sha1Context context;
_sha1Initialize(&context);
_sha1Update(&context, pData, nBytes, copyFunc);
_sha1Final(pHash, &context);
}
#endif /* __NV_SHA1_H__ */