summaryrefslogtreecommitdiff
path: root/bsp/apm32/libraries/APM32F4xx_Library/APM32F4xx_StdPeriphDriver/src/apm32f4xx_hash_sha1.c
blob: 79e539a78e0262a96e2d05844b0dd3e851d413b2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
/*!
 * @file        apm32f4xx_hash_sha1.c
 *
 * @brief       This file provides high level functions to compute the HASH SHA1 and
 *              HMAC SHA1 Digest of an input message.
 *
 * @version     V1.0.2
 *
 * @date        2022-06-23
 *
 * @attention
 *
 *  Copyright (C) 2021-2022 Geehy Semiconductor
 *
 *  You may not use this file except in compliance with the
 *  GEEHY COPYRIGHT NOTICE (GEEHY SOFTWARE PACKAGE LICENSE).
 *
 *  The program is only for reference, which is distributed in the hope
 *  that it will be usefull and instructional for customers to develop
 *  their software. Unless required by applicable law or agreed to in
 *  writing, the program is distributed on an "AS IS" BASIS, WITHOUT
 *  ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the GEEHY SOFTWARE PACKAGE LICENSE for the governing permissions
 *  and limitations under the License.
 */

#include "apm32f4xx_hash.h"

/** @addtogroup APM32F4xx_StdPeriphDriver
  @{
*/

/** @defgroup HASH_SHA1_Driver
  * @brief HASH SHA1 driver modules
  @{
*/

/** @defgroup HASH_SHA1_Functions
  @{
*/

/** @defgroup HASH_SHA1_Macros Macros
  @{
*/

/* HASH SHA1 timeout definition */
#define SHA1_BUSY_TIMEOUT    ((uint32_t) 0x00010000)

/**@} end of group HASH_SHA1_Macros */

/*!
 * @brief     Compute the HASH SHA1 digest
 *
 * @param     inBuffer: pointer to the input buffer to be treated
 *
 * @param     lenBuffer: length of the input buffer.
 *
 * @param     outBuffer: the returned digest.
 *
 * @retval    An ErrorStatus enumeration value:
 *            SUCCESS: digest computation done
 *            ERROR: digest computation failed
 *
 */
uint8_t HASH_ComputeSHA1(uint8_t *inBuffer, uint32_t lenBuffer,
                         uint8_t outBuffer[20])
{
    HASH_Config_T hashSHA1Config;
    HASH_MessageDigest_T hashSHA1MessageDigest;
    uint16_t nBufferBits = 0;
    uint32_t m = 0;
    uint32_t inBufferaddr  = (uint32_t)inBuffer;
    uint32_t outBufferaddr = (uint32_t)outBuffer;

    nBufferBits = (lenBuffer % 4) * 8;

    HASH_Reset();

    /* Configure the number of valid bits in last word of the data */
    hashSHA1Config.algoSelect = HASH_ALGO_SELECTION_SHA1;
    hashSHA1Config.algoMode = HASH_ALGO_MODE_HASH;
    hashSHA1Config.dataType = HASH_DATA_TYPE_8B;
    HASH_Config(&hashSHA1Config);
    HASH_ConfigLastWordValidBitsNbr(nBufferBits);

    /* Write the input block in the IN FIFO */
    for (m = 0; m < lenBuffer; m += 4)
    {
        HASH_WritesInputData(*(uint32_t *)inBufferaddr);
        inBufferaddr += 4;
    }

    /* Start the HASH processor */
    HASH_StartDigest();

    /* wait until the Busy flag is RESET */
    if (HASH_WaitForCompute(SHA1_BUSY_TIMEOUT) != 0)
    {
        return ERROR;
    }
    else
    {
        /* Read the message digest */
        HASH_ReadDigest(&hashSHA1MessageDigest);

        *(uint32_t *)(outBufferaddr)  = __REV(hashSHA1MessageDigest.Data[0]);

        outBufferaddr += 4;
        *(uint32_t *)(outBufferaddr)  = __REV(hashSHA1MessageDigest.Data[1]);

        outBufferaddr += 4;
        *(uint32_t *)(outBufferaddr)  = __REV(hashSHA1MessageDigest.Data[2]);

        outBufferaddr += 4;
        *(uint32_t *)(outBufferaddr)  = __REV(hashSHA1MessageDigest.Data[3]);

        outBufferaddr += 4;
        *(uint32_t *)(outBufferaddr)  = __REV(hashSHA1MessageDigest.Data[4]);
    }

    return SUCCESS;
}

/*!
 * @brief     Compute the HMAC SHA1 digest
 *
 * @param     key: pointer to the Key used for HMAC
 *
 * @param     lenkey: length of the Key used for HMAC
 *
 * @param     inBuffer: pointer to the Input buffer to be treated
 *
 * @param     lenBuffer: length of the Input buffer
 *
 * @param     outBuffer: the returned digest
 *
 * @retval    An ErrorStatus enumeration value:
 *            SUCCESS: digest computation done
 *            ERROR: digest computation failed
 *
 */
uint8_t HMAC_ComputeSHA1(uint8_t *key, uint32_t lenkey, uint8_t *inBuffer,
                         uint32_t lenBuffer, uint8_t outBuffer[20])
{
    HASH_Config_T hmacSHA1Config;
    HASH_MessageDigest_T hashSHA1MessageDigest;
    uint16_t nBufferBits = 0;
    uint16_t nuValidKey = 0;
    uint32_t m = 0;
    uint32_t keyaddr    = (uint32_t)key;
    uint32_t inputaddr  = (uint32_t)inBuffer;
    uint32_t outputaddr = (uint32_t)outBuffer;

    nBufferBits = 8 * (lenBuffer % 4);
    nuValidKey = 8 * (lenkey % 4);

    HASH_Reset();

    /* HASH Configuration */
    hmacSHA1Config.algoSelect = HASH_ALGO_SELECTION_SHA1;
    hmacSHA1Config.algoMode = HASH_ALGO_MODE_HMAC;
    hmacSHA1Config.dataType = HASH_DATA_TYPE_8B;

    if (lenkey > 64)
    {
        hmacSHA1Config.hmacKeyType = HASH_HMAC_KEY_TYPE_LONGKEY;
    }
    else
    {
        hmacSHA1Config.hmacKeyType = HASH_HMAC_KEY_TYPE_SHORTKEY;
    }

    HASH_Config(&hmacSHA1Config);
    HASH_ConfigLastWordValidBitsNbr(nuValidKey);

    /* Write the key */
    for (m = 0; m < lenkey; m += 4)
    {
        HASH_WritesInputData(*(uint32_t *)keyaddr);
        keyaddr += 4;
    }

    HASH_StartDigest();

    /* wait until the Busy flag is RESET */
    if (HASH_WaitForCompute(SHA1_BUSY_TIMEOUT) != 0)
    {
        return ERROR;
    }
    else
    {
        HASH_ConfigLastWordValidBitsNbr(nBufferBits);

        for (m = 0; m < lenkey; m += 4)
        {
            HASH_WritesInputData(*(uint32_t *)inputaddr);
            inputaddr += 4;
        }

        HASH_StartDigest();

        /* wait until the Busy flag is RESET */
        if (HASH_WaitForCompute(SHA1_BUSY_TIMEOUT) != 0)
        {
            return ERROR;
        }
        else
        {
            HASH_ConfigLastWordValidBitsNbr(nuValidKey);
            /* Write the key */
            keyaddr = (uint32_t)key;

            for (m = 0; m < lenkey; m += 4)
            {
                HASH_WritesInputData(*(uint32_t *)keyaddr);
                keyaddr += 4;
            }

            /* Start the HASH processor */
            HASH_StartDigest();

            /* wait until the Busy flag is RESET */
            if (HASH_WaitForCompute(SHA1_BUSY_TIMEOUT) != 0)
            {
                return ERROR;
            }
            else
            {
                /* Read the message digest */
                HASH_ReadDigest(&hashSHA1MessageDigest);
                *(uint32_t *)(outputaddr)  = __REV(hashSHA1MessageDigest.Data[0]);

                outputaddr += 4;
                *(uint32_t *)(outputaddr)  = __REV(hashSHA1MessageDigest.Data[1]);

                outputaddr += 4;
                *(uint32_t *)(outputaddr)  = __REV(hashSHA1MessageDigest.Data[2]);

                outputaddr += 4;
                *(uint32_t *)(outputaddr)  = __REV(hashSHA1MessageDigest.Data[3]);

                outputaddr += 4;
                *(uint32_t *)(outputaddr)  = __REV(hashSHA1MessageDigest.Data[4]);
            }
        }
    }

    return SUCCESS;
}

/**@} end of group HASH_SHA1_Functions */
/**@} end of group HASH_SHA1_Driver */
/**@} end of group APM32F4xx_StdPeriphDriver */