Compare commits

...

4 Commits

Author SHA1 Message Date
Bernhard Reiter
cb0b677acb Merge branch 'patch-1' into 'master'
Update intro.rst (minor): improve English

See merge request gnuk-team/gnuk/gnuk!4
2024-05-11 14:22:38 +00:00
NIIBE Yutaka
de9652726b
Version 2.2.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2024-04-20 11:20:40 +09:00
NIIBE Yutaka
739f17781c
keccak.c also provides SHA-3 and SHAKE128.
Signed-off-by: NIIBE Yutaka <gniibe@fsij.org>
2024-04-18 14:09:57 +09:00
Bernhard Reiter
212dcd1755 Update intro.rst (minor): improve English 2020-01-14 08:07:53 +00:00
11 changed files with 194 additions and 86 deletions

View File

@ -1,3 +1,13 @@
2024-04-20 NIIBE Yutaka <gniibe@fsij.org>
* VERSION: Version 2.2.
2024-04-18 NIIBE Yutaka <gniibe@fsij.org>
* src/keccak.c, src/keccak.h: Rename. Also offer SHA-3.
* src/ecc-ed448.c (ed448_sign): Use keccak_context.
* src/openpgp-do.c (proc_key_import, gpg_do_keygen): Likewise.
2024-02-02 NIIBE Yutaka <gniibe@fsij.org>
* src/modinv.c (modinv_normalize): Fix the computation.

9
NEWS
View File

@ -3,11 +3,16 @@ Gnuk NEWS - User visible changes
* Major changes in Gnuk 2.2
Released 202?-??-??, by NIIBE Yutaka
Released 2024-04-20, by NIIBE Yutaka
** Modular inverse by safegcd256 for Ed25519 and X25519 computation
Ed25519 and X25519 computation are now faster with safegcd256.
Ed25519 and X25519 computation are now a bit faster with safegcd256.
** X25519 with 2^25.5 limb
X25519 computation is done with 2^25.5 limb. It may be better on
other MCUs.
* Major changes in Gnuk 2.1

29
README
View File

@ -1,14 +1,14 @@
Gnuk - An Implementation of USB Cryptographic Token for GnuPG
Version 2.1
2023-09-05
Version 2.2
2024-04-20
Niibe Yutaka
Free Software Initiative of Japan
Release Notes
=============
This is the release of Gnuk, version 2.1, which has major clean up
This is the release of Gnuk, version 2.2, which has major clean up
from Gnuk 1.2. Many (questionable) features have been removed.
It has supports of Ed25519 and X25519 (ECDH on Curve25519). It also
@ -161,9 +161,7 @@ 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://brg.a2hosted.com//oldsite/cryptography_technology/sha/index.php
(was at:
http://gladman.plushost.co.uk/oldsite/cryptography_technology/sha/index.php)
https://web.archive.org/web/20140314032610/http://gladman.plushost.co.uk/oldsite/cryptography_technology/sha/index.php
License
@ -257,13 +255,10 @@ You need GNU toolchain and newlib for 'arm-none-eabi' target.
On Debian we can install the packages of gcc-arm-none-eabi
and its friends. I'm using:
binutils-arm-none-eabi 2.40-2+18+b1
gcc-arm-none-eabi 15:12.2.rel1-1
picolibc-arm-none-eabi 1.8-1
gdb-multiarch 13.1-3
Or else, see https://launchpad.net/gcc-arm-embedded for preparation of
GNU Toolchain for 'arm-none-eabi' target.
binutils-arm-none-eabi 2.41.90.20240115-1+23
gcc-arm-none-eabi 15:13.2.rel1-2
picolibc-arm-none-eabi 1.8.6-2
gdb-multiarch 13.2-1
Change directory to `src':
@ -312,9 +307,9 @@ Flying Stone Tiny 01
If you are using Flying Stone Tiny 01, you need a SWD writer.
OpenOCD 0.9.0 now supports ST-Link/V2. We can use it like:
OpenOCD 0.12.0 supports ST-Link/V2. We can use it like:
$ openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg \
$ openocd -f interface/stlink.cfg -f target/stm32f1x.cfg \
-c "program build/gnuk.elf verify reset exit"
@ -338,7 +333,7 @@ How to protect flash ROM
To protect, invoke OpenOCD like (for FST-01):
$ openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg \
$ openocd -f interface/stlink.cfg -f target/stm32f1x.cfg \
-c init -c "reset halt" -c "stm32f1x lock 0" -c reset -c exit
After power-off / power-on sequence, the contents of flash ROM cannot
@ -346,7 +341,7 @@ be accessible from JTAG debugger.
Unprotecting is:
$ openocd -f interface/stlink-v2.cfg -f target/stm32f1x.cfg \
$ openocd -f interface/stlink.cfg -f target/stm32f1x.cfg \
-c init -c "reset halt" -c "stm32f1x unlock 0" -c reset -c exit
Upon unprotection, flash is erased.

View File

@ -1 +1 @@
release/2.1
release/2.2

View File

@ -5,35 +5,35 @@ Introduction
What's Gnuk?
------------
Gnuk is an implementation of USB cryptographic token for GNU Privacy
Guard. Gnuk supports OpenPGP card protocol version 2, and it runs on
STM32F103 processor.
Gnuk is an implementation of an USB cryptographic token for GNU Privacy
Guard. It supports the OpenPGP card protocol version 2, and runs on
the STM32F103 processor.
This document explains about Gnuk 1.2, which comes with ECC algorithm.
This document explains Gnuk 1.2, which comes with the ECC algorithm.
Cryptographic token and feature of Gnuk
---------------------------------------
Cryptographic token is a store of private keys and it computes cryptographic
A cryptographic token is a store of private keys and it computes cryptographic
functions on the device.
The idea is to separate important secrets to independent device,
The idea is to separate important secrets to an independent device,
from where nobody can extract them.
Development Environment
-----------------------
See :doc:`development` for development environment for Gnuk.
Gnuk is developed on the environment where there are only Free Software.
See :doc:`development` for the development environment for Gnuk.
Gnuk is developed on an environment where there is only Free Software.
Target boards for running Gnuk
------------------------------
Hardware requirement for Gnuk is the micro controller STM32F103.
In version 1.2, Gnuk supports following boards.
In version 1.2, Gnuk supports the following boards:
* FST-01 (Flying Stone Tiny ZERO-ONE)

View File

@ -13,7 +13,7 @@ CSRC = main.c \
modp256k1.c jpc_p256k1.c ec_p256k1.c call-ec_p256k1.c \
mod25638.c ecc-ed25519.c ecc-x25519.c sha512.c \
p448.c ecc-x448.c \
ecc-ed448.c shake256.c \
ecc-ed448.c keccak.c \
random.c neug.c sha256.c
INCDIR =

View File

@ -3,7 +3,7 @@
* the twisted Edwards curve: -x^2 + y^2 = 1 + d*x^2*y^2
* d = -39081
*
* Copyright (C) 2021 Free Software Initiative of Japan
* Copyright (C) 2021, 2024 Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of Gnuk, a GnuPG USB Token implementation.
@ -41,7 +41,7 @@
#include <string.h>
#include "p448.h"
#include "shake256.h"
#include "keccak.h"
#define C_WORDS 7
@ -761,7 +761,7 @@ ed448_sign (uint8_t *out, const uint8_t *input, unsigned int ilen,
const uint8_t *a_in, const uint8_t *seed, const uint8_t *pk)
{
bn448 a[1], k[1], s[1];
shake_context ctx;
keccak_context ctx;
const unsigned char x_olen[2] = { 0, 0 };
uint32_t hash[BN912_WORDS];
uint8_t r[57];

View File

@ -1,7 +1,7 @@
/*
* shake256.c -- Compute SHAKE hash.
* keccak.c -- Compute Keccak hash.
*
* Copyright (C) 2021 Free Software Initiative of Japan
* Copyright (C) 2021, 2024 Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
* This file is a part of Gnuk, a GnuPG USB Token implementation.
@ -17,7 +17,7 @@
* License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*
*/
@ -29,8 +29,25 @@
* August 2015.
*/
#define SHAKE_BITS 256
#define SHAKE_INDEX_MAX (200 - (SHAKE_BITS >> 2))
#define INDEX_MAX(cap) (200 - (cap >> 3))
#define SHAKE256_CAPACITY 512
#define SHAKE256_INDEX_MAX INDEX_MAX (SHAKE256_CAPACITY)
#define SHAKE128_CAPACITY 256
#define SHAKE128_INDEX_MAX INDEX_MAX (SHAKE128_CAPACITY)
#define SHA3_512_CAPACITY 1024
#define SHA3_512_INDEX_MAX INDEX_MAX (SHA3_512_CAPACITY)
/*
* SHAKE is defined appending 11 at the end to RawSHAKE,
* RawSHAKE is defined adding 11 at the end to KECCAK,
* and KECCACK uses pad10*1 at the end.
* This means adding 111110*1 at the end.
*/
#define SHAKE_SUFFIX 0x1F
#define SHA3_SUFFIX 0x06
/*
* b=1600
@ -43,7 +60,8 @@
#include <stdint.h>
#include <string.h>
#include "shake256.h"
#include <stdarg.h>
#include "keccak.h"
/* Round constants in iota step. */
static const uint64_t rc[24] = {
@ -144,59 +162,128 @@ keccak_f1600 (uint64_t s[25])
}
}
void
shake256_start (struct shake_context *shake)
{
memset (shake, 0, sizeof (shake_context));
}
void
shake256_update (struct shake_context *shake,
const unsigned char *src, unsigned int size)
static void
keccak_update (struct keccak_context *keccak,
const unsigned char *src, unsigned int size)
{
if (size == 0)
return;
while (1)
{
absorb (shake->state, shake->index, *src++);
if (++shake->index == SHAKE_INDEX_MAX)
absorb (keccak->state, keccak->index, *src++);
if (++keccak->index == keccak->index_max)
{
keccak_f1600 (shake->state);
shake->index = 0;
keccak_f1600 (keccak->state);
keccak->index = 0;
}
if (--size == 0)
break;
}
}
void
shake256_finish (struct shake_context *shake,
unsigned char *dst, unsigned int size)
static void
keccak_finish (struct keccak_context *keccak,
unsigned char *dst, unsigned int size, uint8_t suffix)
{
if (size == 0)
return;
/*
* SHAKE is defined appending 11 at the end to RawSHAKE,
* RawSHAKE is defined adding 11 at the end to KECCAK,
* and KECCACK uses pad10*1 at the end.
* This means adding 111110*1 at the end.
*/
absorb (shake->state, shake->index, 0x1F);
absorb (shake->state, SHAKE_INDEX_MAX - 1, 0x80);
keccak_f1600 (shake->state);
shake->index = 0;
absorb (keccak->state, keccak->index, suffix);
absorb (keccak->state, keccak->index_max - 1, 0x80);
keccak_f1600 (keccak->state);
keccak->index = 0;
while (1)
{
*dst++ = squeeze (shake->state, shake->index);
*dst++ = squeeze (keccak->state, keccak->index);
if (--size == 0)
break;
if (++shake->index == SHAKE_INDEX_MAX)
if (++keccak->index == keccak->index_max)
{
keccak_f1600 (shake->state);
shake->index = 0;
keccak_f1600 (keccak->state);
keccak->index = 0;
}
}
}
void
shake128_start (struct keccak_context *shake)
{
memset (shake, 0, sizeof (keccak_context));
shake->index_max = SHAKE128_INDEX_MAX;
}
void
shake256_start (struct keccak_context *shake)
{
memset (shake, 0, sizeof (keccak_context));
shake->index_max = SHAKE256_INDEX_MAX;
}
void
shake128_update (struct keccak_context *shake,
const unsigned char *src, unsigned int size)
{
keccak_update (shake, src, size);
}
void
shake256_update (struct keccak_context *shake,
const unsigned char *src, unsigned int size)
{
keccak_update (shake, src, size);
}
void
shake128_finish (struct keccak_context *shake,
unsigned char *dst, unsigned int size)
{
keccak_finish (shake, dst, size, SHAKE_SUFFIX);
}
void
shake256_finish (struct keccak_context *shake,
unsigned char *dst, unsigned int size)
{
keccak_finish (shake, dst, size, SHAKE_SUFFIX);
}
void
shake256v (uint8_t *out, size_t outlen, ...)
{
struct keccak_context ctx;
va_list ap;
void *p;
size_t len;
shake256_start (&ctx);
va_start (ap, outlen);
while (1)
{
p = va_arg (ap, void *);
len = va_arg (ap, size_t);
if (!p)
break;
shake256_update (&ctx, p, len);
}
va_end (ap);
shake256_finish (&ctx, out, outlen);
}
void
sha3_512 (uint8_t h[64], const uint8_t *in, size_t inlen)
{
struct keccak_context ctx;
memset (&ctx, 0, sizeof (keccak_context));
ctx.index_max = SHA3_512_INDEX_MAX;
keccak_update (&ctx, in, inlen);
keccak_finish (&ctx, h, 64, SHA3_SUFFIX);
}

24
src/keccak.h Normal file
View File

@ -0,0 +1,24 @@
#include <stdint.h>
struct keccak_context {
uint64_t state[25];
uint32_t index : 8;
uint32_t index_max : 8;
};
typedef struct keccak_context keccak_context;
void shake128_start (struct keccak_context *keccak);
void shake128_update (struct keccak_context *keccak,
const unsigned char *src, unsigned int size);
void shake128_finish (struct keccak_context *keccak,
unsigned char *dst, unsigned int size);
void shake256_start (struct keccak_context *keccak);
void shake256_update (struct keccak_context *keccak,
const unsigned char *src, unsigned int size);
void shake256_finish (struct keccak_context *keccak,
unsigned char *dst, unsigned int size);
void shake256v (uint8_t *out, size_t outlen, ...);
void sha3_512 (uint8_t h[64], const uint8_t *in, size_t inlen);

View File

@ -2,7 +2,7 @@
* openpgp-do.c -- OpenPGP card Data Objects (DO) handling
*
* Copyright (C) 2010, 2011, 2012, 2013, 2014, 2015, 2016, 2017, 2018,
* 2020, 2021, 2022
* 2020, 2021, 2022, 2024
* Free Software Initiative of Japan
* Author: NIIBE Yutaka <gniibe@fsij.org>
*
@ -34,7 +34,7 @@
#include "random.h"
#include "aes.h"
#include "sha512.h"
#include "shake256.h"
#include "keccak.h"
/* Forward declaration */
#define CLEAN_PAGE_FULL 1
@ -1567,7 +1567,7 @@ proc_key_import (const uint8_t *data, int len)
}
else if (attr == ALGO_ED448)
{
shake_context ctx;
keccak_context ctx;
uint8_t hash[128];
if (len - 12 != 57)
@ -2348,7 +2348,7 @@ gpg_do_keygen (uint8_t *buf)
}
else if (attr == ALGO_ED448)
{
shake_context ctx;
keccak_context ctx;
rnd = random_bytes_get ();
shake256_start (&ctx);
shake256_update (&ctx, rnd, 32);

View File

@ -1,13 +0,0 @@
#include <stdint.h>
struct shake_context {
uint64_t state[25];
uint32_t index;
};
typedef struct shake_context shake_context;
void shake256_start (struct shake_context *shake);
void shake256_update (struct shake_context *shake,
const unsigned char *src, unsigned int size);
void shake256_finish (struct shake_context *shake,
unsigned char *dst, unsigned int size);