SHA256
This commit is contained in:
15
ChangeLog
15
ChangeLog
@@ -1,6 +1,21 @@
|
||||
2012-06-14 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
KDF is now SHA-256 (was: SHA1).
|
||||
* src/sha256.c: New file. Based on the implementation by Dr Brian
|
||||
Gladman.
|
||||
* src/openpgp.c (cmd_change_password, cmd_reset_user_password):
|
||||
Use sha256.
|
||||
* src/openpgp-do.c (proc_resetting_code, gpg_do_write_prvkey): Likewise.
|
||||
* src/ac.c (verify_user_0, calc_md, verify_admin): Likewise.
|
||||
* src/crypt.mk (CRYPTSRC): Add sha256.c, removing sha1.c.
|
||||
* src/gnuk.h (KEYSTRING_MD_SIZE): It's 32 for SHA-256.
|
||||
|
||||
2012-06-13 Niibe Yutaka <gniibe@fsij.org>
|
||||
|
||||
Bug fixes.
|
||||
* src/main.c (display_interaction): Assign to main_mode.
|
||||
* src/openpgp.c (cmd_change_password): Bug fix for admin less mode
|
||||
to admin full mode. Variable who_old should be admin_authorized.
|
||||
|
||||
Key generation is configure option.
|
||||
* src/configure (keygen): Add --enable-keygen option.
|
||||
|
||||
5
NEWS
5
NEWS
@@ -8,6 +8,11 @@ Gnuk NEWS - User visible changes
|
||||
Finally, key generation is supported. Note that it is very slow. It
|
||||
will takes a few minutes to generate two keys.
|
||||
|
||||
** KDF (Key Derivation Function) is now SHA-256
|
||||
Data encryption key for private keys are computed by KDF (Key
|
||||
Derivation Function, sometimes also is refered as string to key
|
||||
function, S2K). It was SHA1 before, but it is replaced by SHA-256.
|
||||
|
||||
|
||||
* Major changes in Gnuk 0.19
|
||||
|
||||
|
||||
10
README
10
README
@@ -189,6 +189,11 @@ Souce code
|
||||
|
||||
Gnuk source code is under src/ directory.
|
||||
|
||||
Note that SHA-2 hash function implementation, src/sha256.c, is based
|
||||
on the original implementation by Dr. Brian Gladman. See:
|
||||
|
||||
http://gladman.plushost.co.uk/oldsite/cryptography_technology/sha/index.php
|
||||
|
||||
|
||||
License
|
||||
=======
|
||||
@@ -197,7 +202,7 @@ It is distributed under GNU General Public Licence version 3 or later
|
||||
(GPLv3+). Please see src/COPYING.
|
||||
|
||||
Please note that it is distributed with external source code too.
|
||||
Please read relevant licenses for external source code, too.
|
||||
Please read relevant licenses for external source code as well.
|
||||
|
||||
The author(s) of Gnuk expect users of Gnuk will be able to access the
|
||||
source code of Gnuk, so that users can study the code and can modify
|
||||
@@ -221,8 +226,7 @@ Gnuk is distributed with external source code.
|
||||
* polarssl-0.14.0/ -- PolarSSL 0.14.0
|
||||
|
||||
Taken from http://polarssl.org/
|
||||
We use PolarSSL for RSA computation, AES encryption/decryption
|
||||
and SHA-1 computation.
|
||||
We use PolarSSL for RSA computation, AES encryption/decryption.
|
||||
|
||||
The file include/polarssl/bn_mul.h is heavily modified for ARM
|
||||
Cortex-M3.
|
||||
|
||||
25
src/ac.c
25
src/ac.c
@@ -24,9 +24,7 @@
|
||||
#include "config.h"
|
||||
#include "ch.h"
|
||||
#include "gnuk.h"
|
||||
|
||||
#include "polarssl/config.h"
|
||||
#include "polarssl/sha1.h"
|
||||
#include "sha256.h"
|
||||
|
||||
uint8_t volatile auth_status; /* Initialized to AC_NONE_AUTHORIZED */
|
||||
|
||||
@@ -89,7 +87,7 @@ verify_user_0 (uint8_t access, const uint8_t *pw, int buf_len, int pw_len_known,
|
||||
}
|
||||
|
||||
success_one_step:
|
||||
sha1 (pw, pw_len, keystring);
|
||||
sha256 (pw, pw_len, keystring);
|
||||
if (access == AC_PSO_CDS_AUTHORIZED)
|
||||
{
|
||||
r1 = gpg_do_load_prvkey (GPG_KEY_FOR_SIGNING, BY_USER, keystring);
|
||||
@@ -161,28 +159,27 @@ static void
|
||||
calc_md (int count, const uint8_t *salt, const uint8_t *pw, int pw_len,
|
||||
uint8_t md[KEYSTRING_MD_SIZE])
|
||||
{
|
||||
sha1_context sha1_ctx;
|
||||
sha256_context sha256_ctx;
|
||||
|
||||
sha1_starts (&sha1_ctx);
|
||||
sha256_start (&sha256_ctx);
|
||||
|
||||
while (count > pw_len + 8)
|
||||
{
|
||||
sha1_update (&sha1_ctx, salt, 8);
|
||||
sha1_update (&sha1_ctx, pw, pw_len);
|
||||
sha256_update (&sha256_ctx, salt, 8);
|
||||
sha256_update (&sha256_ctx, pw, pw_len);
|
||||
count -= pw_len + 8;
|
||||
}
|
||||
|
||||
if (count <= 8)
|
||||
sha1_update (&sha1_ctx, salt, count);
|
||||
sha256_update (&sha256_ctx, salt, count);
|
||||
else
|
||||
{
|
||||
sha1_update (&sha1_ctx, salt, 8);
|
||||
sha256_update (&sha256_ctx, salt, 8);
|
||||
count -= 8;
|
||||
sha1_update (&sha1_ctx, pw, count);
|
||||
sha256_update (&sha256_ctx, pw, count);
|
||||
}
|
||||
|
||||
sha1_finish (&sha1_ctx, md);
|
||||
memset (&sha1_ctx, 0, sizeof (sha1_ctx));
|
||||
sha256_finish (&sha256_ctx, md);
|
||||
}
|
||||
|
||||
uint8_t keystring_md_pw3[KEYSTRING_MD_SIZE];
|
||||
@@ -283,7 +280,7 @@ verify_admin (const uint8_t *pw, int pw_len)
|
||||
if (r <= 0)
|
||||
return r;
|
||||
|
||||
sha1 (pw, pw_len, keystring_md_pw3);
|
||||
sha256 (pw, pw_len, keystring_md_pw3);
|
||||
auth_status |= AC_ADMIN_AUTHORIZED;
|
||||
return 1;
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
CRYPTDIR = ../polarssl-0.14.0
|
||||
CRYPTSRCDIR = $(CRYPTDIR)/library
|
||||
CRYPTINCDIR = $(CRYPTDIR)/include
|
||||
CRYPTSRC = $(CRYPTSRCDIR)/bignum.c $(CRYPTSRCDIR)/rsa.c $(CRYPTSRCDIR)/sha1.c \
|
||||
CRYPTSRC = $(CRYPTSRCDIR)/bignum.c $(CRYPTSRCDIR)/rsa.c \
|
||||
$(CRYPTSRCDIR)/aes.c \
|
||||
call-rsa.c
|
||||
sha256.c call-rsa.c
|
||||
|
||||
@@ -198,7 +198,7 @@ extern int flash_key_write (uint8_t *key_addr, const uint8_t *key_data, const ui
|
||||
#define KEYSTRING_PASSLEN_SIZE 1
|
||||
#define KEYSTRING_SALT_SIZE 8 /* optional */
|
||||
#define KEYSTRING_ITER_SIZE 1 /* optional */
|
||||
#define KEYSTRING_MD_SIZE 20
|
||||
#define KEYSTRING_MD_SIZE 32
|
||||
#define KEYSTRING_SIZE_PW1 (KEYSTRING_PASSLEN_SIZE+KEYSTRING_MD_SIZE)
|
||||
#define KEYSTRING_SIZE_RC (KEYSTRING_PASSLEN_SIZE+KEYSTRING_MD_SIZE)
|
||||
#define KEYSTRING_SIZE_PW3 (KEYSTRING_PASSLEN_SIZE+KEYSTRING_SALT_SIZE \
|
||||
|
||||
@@ -28,10 +28,10 @@
|
||||
#include "sys.h"
|
||||
#include "gnuk.h"
|
||||
#include "openpgp.h"
|
||||
#include "sha256.h"
|
||||
|
||||
#include "polarssl/config.h"
|
||||
#include "polarssl/aes.h"
|
||||
#include "polarssl/sha1.h"
|
||||
|
||||
#define PASSWORD_ERRORS_MAX 3 /* >= errors, it will be locked */
|
||||
static const uint8_t *pw_err_counter_p[3];
|
||||
@@ -543,7 +543,7 @@ proc_resetting_code (const uint8_t *data, int len)
|
||||
|
||||
newpw_len = len;
|
||||
newpw = data;
|
||||
sha1 (newpw, newpw_len, new_ks);
|
||||
sha256 (newpw, newpw_len, new_ks);
|
||||
new_ks0[0] = newpw_len;
|
||||
r = gpg_change_keystring (admin_authorized, old_ks, BY_RESETCODE, new_ks);
|
||||
if (r <= -2)
|
||||
@@ -780,7 +780,7 @@ gpg_do_write_prvkey (enum kind_of_key kk, const uint8_t *key_data, int key_len,
|
||||
uint8_t ks123_pw1[KEYSTRING_SIZE_PW1];
|
||||
|
||||
ks123_pw1[0] = strlen (OPENPGP_CARD_INITIAL_PW1);
|
||||
sha1 ((uint8_t *)OPENPGP_CARD_INITIAL_PW1,
|
||||
sha256 ((uint8_t *)OPENPGP_CARD_INITIAL_PW1,
|
||||
strlen (OPENPGP_CARD_INITIAL_PW1), ks123_pw1+1);
|
||||
encrypt (ks123_pw1+1, pd->dek_encrypted_1, DATA_ENCRYPTION_KEY_SIZE);
|
||||
}
|
||||
|
||||
@@ -27,8 +27,7 @@
|
||||
#include "gnuk.h"
|
||||
#include "sys.h"
|
||||
#include "openpgp.h"
|
||||
#include "polarssl/config.h"
|
||||
#include "polarssl/sha1.h"
|
||||
#include "sha256.h"
|
||||
|
||||
#define CLS(a) a.cmd_apdu_head[0]
|
||||
#define INS(a) a.cmd_apdu_head[1]
|
||||
@@ -225,6 +224,7 @@ cmd_change_password (void)
|
||||
const uint8_t *newpw;
|
||||
int pw_len, newpw_len;
|
||||
int who = p2 - 0x80;
|
||||
int who_old;
|
||||
int r;
|
||||
|
||||
DEBUG_INFO ("Change PW\r\n");
|
||||
@@ -244,6 +244,7 @@ cmd_change_password (void)
|
||||
const uint8_t *ks_pw1 = gpg_do_read_simple (NR_DO_KEYSTRING_PW1);
|
||||
|
||||
pw_len = verify_user_0 (AC_PSO_CDS_AUTHORIZED, pw, len, -1, ks_pw1);
|
||||
who_old = who;
|
||||
|
||||
if (pw_len < 0)
|
||||
{
|
||||
@@ -284,14 +285,15 @@ cmd_change_password (void)
|
||||
newpw = pw + pw_len;
|
||||
newpw_len = len - pw_len;
|
||||
gpg_set_pw3 (newpw, newpw_len);
|
||||
who_old = admin_authorized;
|
||||
}
|
||||
}
|
||||
|
||||
sha1 (pw, pw_len, old_ks);
|
||||
sha1 (newpw, newpw_len, new_ks);
|
||||
sha256 (pw, pw_len, old_ks);
|
||||
sha256 (newpw, newpw_len, new_ks);
|
||||
new_ks0[0] = newpw_len;
|
||||
|
||||
r = gpg_change_keystring (who, old_ks, who, new_ks);
|
||||
r = gpg_change_keystring (who_old, old_ks, who, new_ks);
|
||||
if (r <= -2)
|
||||
{
|
||||
DEBUG_INFO ("memory error.\r\n");
|
||||
@@ -366,8 +368,8 @@ cmd_reset_user_password (void)
|
||||
pw_len = ks_rc[0];
|
||||
newpw = pw + pw_len;
|
||||
newpw_len = len - pw_len;
|
||||
sha1 (pw, pw_len, old_ks);
|
||||
sha1 (newpw, newpw_len, new_ks);
|
||||
sha256 (pw, pw_len, old_ks);
|
||||
sha256 (newpw, newpw_len, new_ks);
|
||||
new_ks0[0] = newpw_len;
|
||||
r = gpg_change_keystring (BY_RESETCODE, old_ks, BY_USER, new_ks);
|
||||
if (r <= -2)
|
||||
@@ -418,7 +420,7 @@ cmd_reset_user_password (void)
|
||||
|
||||
newpw_len = len;
|
||||
newpw = pw;
|
||||
sha1 (newpw, newpw_len, new_ks);
|
||||
sha256 (newpw, newpw_len, new_ks);
|
||||
new_ks0[0] = newpw_len;
|
||||
r = gpg_change_keystring (admin_authorized, old_ks, BY_USER, new_ks);
|
||||
if (r <= -2)
|
||||
|
||||
223
src/sha256.c
Normal file
223
src/sha256.c
Normal file
@@ -0,0 +1,223 @@
|
||||
/*
|
||||
* sha256.c -- Compute SHA-256 hash
|
||||
*
|
||||
* Just for little endian architecture.
|
||||
*
|
||||
* Code taken from:
|
||||
* http://gladman.plushost.co.uk/oldsite/cryptography_technology/sha/index.php
|
||||
*
|
||||
* File names are sha2.c, sha2.h, brg_types.h, brg_endian.h
|
||||
* in the archive sha2-07-01-07.zip.
|
||||
*
|
||||
* Code is modified in the style of PolarSSL API.
|
||||
*
|
||||
* See original copyright notice below.
|
||||
*/
|
||||
/*
|
||||
---------------------------------------------------------------------------
|
||||
Copyright (c) 2002, Dr Brian Gladman, Worcester, UK. All rights reserved.
|
||||
|
||||
LICENSE TERMS
|
||||
|
||||
The free distribution and use of this software in both source and binary
|
||||
form is allowed (with or without changes) provided that:
|
||||
|
||||
1. distributions of this source code include the above copyright
|
||||
notice, this list of conditions and the following disclaimer;
|
||||
|
||||
2. distributions in binary form include the above copyright
|
||||
notice, this list of conditions and the following disclaimer
|
||||
in the documentation and/or other associated materials;
|
||||
|
||||
3. the copyright holder's name is not used to endorse products
|
||||
built using this software without specific written permission.
|
||||
|
||||
ALTERNATIVELY, provided that this notice is retained in full, this product
|
||||
may be distributed under the terms of the GNU General Public License (GPL),
|
||||
in which case the provisions of the GPL apply INSTEAD OF those given above.
|
||||
|
||||
DISCLAIMER
|
||||
|
||||
This software is provided 'as is' with no explicit or implied warranties
|
||||
in respect of its properties, including, but not limited to, correctness
|
||||
and/or fitness for purpose.
|
||||
---------------------------------------------------------------------------
|
||||
Issue Date: 01/08/2005
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "sha256.h"
|
||||
|
||||
#define SHA256_DIGEST_SIZE 32
|
||||
#define SHA256_BLOCK_SIZE 64
|
||||
#define SHA256_MASK (SHA256_BLOCK_SIZE - 1)
|
||||
|
||||
static void bswap32_buf (uint32_t *p, int n)
|
||||
{
|
||||
while (n--)
|
||||
p[n] = __builtin_bswap32 (p[n]); /* bswap32 is GCC extention */
|
||||
}
|
||||
|
||||
#define rotr32(x,n) (((x) >> n) | ((x) << (32 - n)))
|
||||
|
||||
#define ch(x,y,z) ((z) ^ ((x) & ((y) ^ (z))))
|
||||
#define maj(x,y,z) (((x) & (y)) | ((z) & ((x) ^ (y))))
|
||||
|
||||
/* round transforms for SHA256 compression functions */
|
||||
#define vf(n,i) v[(n - i) & 7]
|
||||
|
||||
#define hf(i) (p[i & 15] += \
|
||||
g_1(p[(i + 14) & 15]) + p[(i + 9) & 15] + g_0(p[(i + 1) & 15]))
|
||||
|
||||
#define v_cycle(i,j) \
|
||||
vf(7,i) += (j ? hf(i) : p[i]) + k_0[i+j] \
|
||||
+ s_1(vf(4,i)) + ch(vf(4,i),vf(5,i),vf(6,i)); \
|
||||
vf(3,i) += vf(7,i); \
|
||||
vf(7,i) += s_0(vf(0,i))+ maj(vf(0,i),vf(1,i),vf(2,i))
|
||||
|
||||
#define s_0(x) (rotr32((x), 2) ^ rotr32((x), 13) ^ rotr32((x), 22))
|
||||
#define s_1(x) (rotr32((x), 6) ^ rotr32((x), 11) ^ rotr32((x), 25))
|
||||
#define g_0(x) (rotr32((x), 7) ^ rotr32((x), 18) ^ ((x) >> 3))
|
||||
#define g_1(x) (rotr32((x), 17) ^ rotr32((x), 19) ^ ((x) >> 10))
|
||||
#define k_0 k256
|
||||
|
||||
const uint32_t k256[64] = {
|
||||
0X428A2F98, 0X71374491, 0XB5C0FBCF, 0XE9B5DBA5,
|
||||
0X3956C25B, 0X59F111F1, 0X923F82A4, 0XAB1C5ED5,
|
||||
0XD807AA98, 0X12835B01, 0X243185BE, 0X550C7DC3,
|
||||
0X72BE5D74, 0X80DEB1FE, 0X9BDC06A7, 0XC19BF174,
|
||||
0XE49B69C1, 0XEFBE4786, 0X0FC19DC6, 0X240CA1CC,
|
||||
0X2DE92C6F, 0X4A7484AA, 0X5CB0A9DC, 0X76F988DA,
|
||||
0X983E5152, 0XA831C66D, 0XB00327C8, 0XBF597FC7,
|
||||
0XC6E00BF3, 0XD5A79147, 0X06CA6351, 0X14292967,
|
||||
0X27B70A85, 0X2E1B2138, 0X4D2C6DFC, 0X53380D13,
|
||||
0X650A7354, 0X766A0ABB, 0X81C2C92E, 0X92722C85,
|
||||
0XA2BFE8A1, 0XA81A664B, 0XC24B8B70, 0XC76C51A3,
|
||||
0XD192E819, 0XD6990624, 0XF40E3585, 0X106AA070,
|
||||
0X19A4C116, 0X1E376C08, 0X2748774C, 0X34B0BCB5,
|
||||
0X391C0CB3, 0X4ED8AA4A, 0X5B9CCA4F, 0X682E6FF3,
|
||||
0X748F82EE, 0X78A5636F, 0X84C87814, 0X8CC70208,
|
||||
0X90BEFFFA, 0XA4506CEB, 0XBEF9A3F7, 0XC67178F2,
|
||||
};
|
||||
|
||||
void
|
||||
sha256_process (sha256_context *ctx)
|
||||
{
|
||||
uint32_t i;
|
||||
uint32_t *p = ctx->wbuf;
|
||||
uint32_t v[8];
|
||||
|
||||
memcpy (v, ctx->state, 8 * sizeof (uint32_t));
|
||||
|
||||
for (i = 0; i < 64; i += 16)
|
||||
{
|
||||
v_cycle ( 0, i);
|
||||
v_cycle ( 1, i);
|
||||
v_cycle ( 2, i);
|
||||
v_cycle ( 3, i);
|
||||
v_cycle ( 4, i);
|
||||
v_cycle ( 5, i);
|
||||
v_cycle ( 6, i);
|
||||
v_cycle ( 7, i);
|
||||
v_cycle ( 8, i);
|
||||
v_cycle ( 9, i);
|
||||
v_cycle (10, i);
|
||||
v_cycle (11, i);
|
||||
v_cycle (12, i);
|
||||
v_cycle (13, i);
|
||||
v_cycle (14, i);
|
||||
v_cycle (15, i);
|
||||
}
|
||||
|
||||
ctx->state[0] += v[0];
|
||||
ctx->state[1] += v[1];
|
||||
ctx->state[2] += v[2];
|
||||
ctx->state[3] += v[3];
|
||||
ctx->state[4] += v[4];
|
||||
ctx->state[5] += v[5];
|
||||
ctx->state[6] += v[6];
|
||||
ctx->state[7] += v[7];
|
||||
}
|
||||
|
||||
void
|
||||
sha256_update (sha256_context *ctx, const unsigned char *input,
|
||||
unsigned int ilen)
|
||||
{
|
||||
uint32_t left = (ctx->total[0] & SHA256_MASK);
|
||||
uint32_t fill = SHA256_BLOCK_SIZE - left;
|
||||
|
||||
ctx->total[0] += ilen;
|
||||
if (ctx->total[0] < ilen)
|
||||
ctx->total[1]++;
|
||||
|
||||
while (ilen >= fill)
|
||||
{
|
||||
memcpy (((unsigned char*)ctx->wbuf) + left, input, fill);
|
||||
bswap32_buf (ctx->wbuf, SHA256_BLOCK_SIZE >> 2);
|
||||
sha256_process (ctx);
|
||||
input += fill;
|
||||
ilen -= fill;
|
||||
left = 0;
|
||||
fill = SHA256_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
memcpy (((unsigned char*)ctx->wbuf) + left, input, ilen);
|
||||
}
|
||||
|
||||
void
|
||||
sha256_finish (sha256_context *ctx, unsigned char output[32])
|
||||
{
|
||||
uint32_t last = (ctx->total[0] & SHA256_MASK);
|
||||
|
||||
bswap32_buf (ctx->wbuf, (last + 3) >> 2);
|
||||
|
||||
ctx->wbuf[last >> 2] &= 0xffffff80 << (8 * (~last & 3));
|
||||
ctx->wbuf[last >> 2] |= 0x00000080 << (8 * (~last & 3));
|
||||
|
||||
if (last > SHA256_BLOCK_SIZE - 9)
|
||||
{
|
||||
if (last < 60)
|
||||
ctx->wbuf[15] = 0;
|
||||
sha256_process (ctx);
|
||||
last = 0;
|
||||
}
|
||||
else
|
||||
last = (last >> 2) + 1;
|
||||
|
||||
while (last < 14)
|
||||
ctx->wbuf[last++] = 0;
|
||||
|
||||
ctx->wbuf[14] = (ctx->total[0] >> 29) | (ctx->total[1] << 3);
|
||||
ctx->wbuf[15] = ctx->total[0] << 3;
|
||||
sha256_process (ctx);
|
||||
|
||||
bswap32_buf (ctx->state, SHA256_DIGEST_SIZE >> 2);
|
||||
memcpy (output, ctx->state, SHA256_DIGEST_SIZE);
|
||||
}
|
||||
|
||||
const uint32_t initial_state[8] =
|
||||
{
|
||||
0x6a09e667, 0xbb67ae85, 0x3c6ef372, 0xa54ff53a,
|
||||
0x510e527f, 0x9b05688c, 0x1f83d9ab, 0x5be0cd19
|
||||
};
|
||||
|
||||
void
|
||||
sha256_start (sha256_context *ctx)
|
||||
{
|
||||
ctx->total[0] = ctx->total[1] = 0;
|
||||
memcpy (ctx->state, initial_state, 8 * sizeof(uint32_t));
|
||||
}
|
||||
|
||||
void
|
||||
sha256 (const unsigned char *input, unsigned int ilen,
|
||||
unsigned char output[32])
|
||||
{
|
||||
sha256_context ctx;
|
||||
|
||||
sha256_start (&ctx);
|
||||
sha256_update (&ctx, input, ilen);
|
||||
sha256_finish (&ctx, output);
|
||||
|
||||
memset (&ctx, 0, sizeof (sha256_context));
|
||||
}
|
||||
14
src/sha256.h
Normal file
14
src/sha256.h
Normal file
@@ -0,0 +1,14 @@
|
||||
typedef struct
|
||||
{
|
||||
uint32_t total[2];
|
||||
uint32_t state[8];
|
||||
uint32_t wbuf[16];
|
||||
} sha256_context;
|
||||
|
||||
extern void sha256 (const unsigned char *input, unsigned int ilen,
|
||||
unsigned char output[32]);
|
||||
extern void sha256_start (sha256_context *ctx);
|
||||
extern void sha256_finish (sha256_context *ctx, unsigned char output[32]);
|
||||
extern void sha256_update (sha256_context *ctx, const unsigned char *input,
|
||||
unsigned int ilen);
|
||||
extern void sha256_process (sha256_context *ctx);
|
||||
Reference in New Issue
Block a user