...
 
Commits (29)
......@@ -18,7 +18,7 @@ test:
- build
script:
- make test CONFIG=config/config-ci.mk
- (cd test; valgrind --leak-check=full --error-exitcode=2 ./test)
- (cd test; valgrind --leak-check=full --error-exitcode=2 ./test -v)
- gcovr --exclude test -r . | grep TOTAL
# Publish API Documentation
......@@ -28,7 +28,7 @@ pages:
- test
script:
- make doc
- mv doc/doxy/html/* public/
- mv doc/doxy/html public
artifacts:
paths:
- public
......
......@@ -2,7 +2,7 @@ language: c
script:
- make test CONFIG=config/config-ci.mk
- (cd test; ./test)
- (cd test; ./test -v)
before_install:
- pip install --user -q cpp-coveralls
......
......@@ -22,18 +22,21 @@ Given a version number MAJOR.MINOR.PATCH
* PATCH incremented for bug fixes
[0.1.1] - Unreleased
[0.1.1] - 2020-04-01
--------------------
Added
* ARC4 stream cipher
* Elgamal digital signature
* ARC4 stream cipher.
* Elgamal digital signature.
* Elliptic curve group arithmetics exhaustive unit tests (add/mul).
* DSA key parameters generator.
* SHA-512 and SHA-384
Fixed
* MPI "is_prime" function was not working for primes < 1010 (decimal)
* MPI "is_prime" function was not working for primes < 1010 (decimal).
* ECDSA major fix in one of the NIST curves parameters.
[0.1.0] - 2019-09-23
......@@ -41,19 +44,19 @@ Fixed
Added
* RSA sign/verify functions
* Schoolbook RSA
* AES Key Wrap (RFC-3394)
* RSA sign/verify functions.
* Schoolbook RSA.
* AES Key Wrap (RFC-3394).
Changed
* RSA padding schemes correction
* MPI random prime generation sequence independence from MPI digit size
* Weak PRNG properly renamed to LFSR-113
* RSA padding schemes correction.
* MPI random prime generation sequence independence from MPI digit size.
* Weak PRNG renamed to LFSR-113.
Fixed
* MPI bit-set macro was setting the wrong bit when using 64-bit digits
* MPI bit-set macro was setting the wrong bit when using 64-bit digits.
[0.0.10] - 2019-06-08
......
......@@ -9,6 +9,8 @@ CRY is a small, comprehensive and portable cryptographic library prividing
a good collection of ciphers, hash functions, pseudo-random number generators
and multi-precision integers algorithms.
API Doxygen documentation [here](https://crylib.gitlab.io/cry/).
Symmetric ciphers
-----------------
......
......@@ -19,7 +19,7 @@ CRY_DEBUG=y
################################################################################
#CRY_ARCH_X86_64=y
#CRY_ARCH_x86=y
#CRY_ARCH_X86=y
################################################################################
# Algorithms tweaks
......@@ -37,7 +37,7 @@ CRY_MPI_MUL_COMBA=y
# Karatsuba multiplier enabled, see the mpi_mul.c to set the CUTOFF
CRY_MPI_MUL_KARATSUBA=y
#
# Toom-3 multiplier enabled, see the mpi_mul.c to set the CUTOFF
CRY_MPI_MUL_TOOM3=y
......
No preview for this file type
......@@ -17,8 +17,6 @@
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
......@@ -29,11 +27,11 @@
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
<configuration artifactName="${ProjName}" buildProperties="" description="" id="0.645038386" name="Default" optionalBuildProperties="" parent="org.eclipse.cdt.build.core.prefbase.cfg">
<configuration artifactName="${ProjName}" buildProperties="" description="" id="0.645038386" name="Default" optionalBuildProperties="org.eclipse.cdt.docker.launcher.containerbuild.property.volumes=,org.eclipse.cdt.docker.launcher.containerbuild.property.selectedvolumes=" parent="org.eclipse.cdt.build.core.prefbase.cfg">
<folderInfo id="0.645038386." name="/" resourcePath="">
<toolChain id="cdt.managedbuild.toolchain.gnu.cross.base.1964564816" name="Cross GCC" superClass="cdt.managedbuild.toolchain.gnu.cross.base">
<toolChain id="cdt.managedbuild.toolchain.gnu.cross.base.1964564816" name="Cross GCC" superClass="cdt.managedbuild.toolchain.gnu.cross.base" unusedChildren="cdt.managedbuild.tool.gnu.cross.cpp.compiler;cdt.managedbuild.tool.gnu.cross.cpp.linker;cdt.managedbuild.tool.gnu.cross.c.linker">
<option id="cdt.managedbuild.option.gnu.cross.prefix.187801918" name="Prefix" superClass="cdt.managedbuild.option.gnu.cross.prefix"/>
......@@ -49,29 +47,13 @@
</tool>
<tool id="cdt.managedbuild.tool.gnu.cross.cpp.compiler.732622307" name="Cross G++ Compiler" superClass="cdt.managedbuild.tool.gnu.cross.cpp.compiler"/>
<tool id="cdt.managedbuild.tool.gnu.cross.c.linker.1601373088" name="Cross GCC Linker" superClass="cdt.managedbuild.tool.gnu.cross.c.linker">
<inputType id="cdt.managedbuild.tool.gnu.c.linker.input.629364390" superClass="cdt.managedbuild.tool.gnu.c.linker.input">
<additionalInput kind="additionalinputdependency" paths="$(USER_OBJS)"/>
<additionalInput kind="additionalinput" paths="$(LIBS)"/>
</inputType>
</tool>
<tool id="cdt.managedbuild.tool.gnu.cross.cpp.linker.1563026372" name="Cross G++ Linker" superClass="cdt.managedbuild.tool.gnu.cross.cpp.linker"/>
<tool id="cdt.managedbuild.tool.gnu.cross.archiver.1385413374" name="Cross GCC Archiver" superClass="cdt.managedbuild.tool.gnu.cross.archiver"/>
<tool id="cdt.managedbuild.tool.gnu.cross.assembler.418073746" name="Cross GCC Assembler" superClass="cdt.managedbuild.tool.gnu.cross.assembler">
<inputType id="cdt.managedbuild.tool.gnu.assembler.input.2123397635" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
</tool>
<tool id="cdt.managedbuild.tool.gnu.cross.archiver.1385413374" name="Cross GCC Archiver" superClass="cdt.managedbuild.tool.gnu.cross.archiver"/>
</toolChain>
......
......@@ -9,21 +9,21 @@
#include <cry/mpi.h>
struct cry_dsa_ctx {
cry_mpi g;
cry_mpi p;
cry_mpi q;
cry_mpi p; /**< Prime modulus */
cry_mpi q; /**< Prime modulus subgroup (prime divisor of p-1) */
cry_mpi g; /**< Subgroup generator */
cry_mpi pvt; /**< Private signing key */
cry_mpi pub; /**< Public verification key */
};
typedef struct cry_dsa_ctx cry_dsa_ctx;
struct cry_dsa_signature {
cry_mpi r;
cry_mpi s;
struct cry_dsa_sig {
cry_mpi r; /**< Signature first component */
cry_mpi s; /**< Signature second component */
};
typedef struct cry_dsa_signature cry_dsa_signature;
typedef struct cry_dsa_sig cry_dsa_sig;
#ifdef __cplusplus
extern "C" {
......@@ -33,12 +33,14 @@ int cry_dsa_init(cry_dsa_ctx *ctx);
void cry_dsa_clear(cry_dsa_ctx *ctx);
int cry_dsa_sign(cry_dsa_ctx *ctx, cry_dsa_signature *sign,
int cry_dsa_sign(cry_dsa_ctx *ctx, cry_dsa_sig *sig,
const unsigned char *in, size_t len);
int cry_dsa_verify(cry_dsa_ctx *ctx, const cry_dsa_signature *sign,
int cry_dsa_verify(cry_dsa_ctx *ctx, const cry_dsa_sig *sig,
const unsigned char *in, size_t len);
int cry_dsa_keygen(cry_dsa_ctx *ctx, unsigned int l);
#ifdef __cplusplus
}
#endif
......
......@@ -9,31 +9,35 @@
#include <cry/ecp.h>
struct cry_ecdsa_ctx {
cry_ecp_grp ec; /**< Elliptic curve group parameters */
cry_ecp_grp grp; /**< Elliptic curve group parameters */
cry_mpi d; /**< Private signing key */
cry_ecp q; /**< Public verification key */
};
typedef struct cry_ecdsa_ctx cry_ecdsa_ctx;
struct cry_ecdsa_signature {
cry_mpi r;
cry_mpi s;
struct cry_ecdsa_sig {
cry_mpi r; /* Signature first component */
cry_mpi s; /* Signature second component */
};
typedef struct cry_ecdsa_signature cry_ecdsa_signature;
typedef struct cry_ecdsa_sig cry_ecdsa_sig;
#ifdef __cplusplus
extern "C" {
#endif
int cry_ecdsa_sign(cry_ecdsa_ctx *ctx, cry_ecdsa_signature *sign,
int cry_ecdsa_sign(cry_ecdsa_ctx *ctx, cry_ecdsa_sig *sig,
const unsigned char *in, size_t len);
int cry_ecdsa_verify(cry_ecdsa_ctx *ctx, const cry_ecdsa_signature *sign,
int cry_ecdsa_verify(cry_ecdsa_ctx *ctx, const cry_ecdsa_sig *sig,
const unsigned char *in, size_t len);
int cry_ecdsa_keygen(const cry_ecp_grp *ec, cry_mpi *d, cry_ecp *q);
int cry_ecdsa_init(cry_ecdsa_ctx *ctx, int grp);
void cry_ecdsa_clear(cry_ecdsa_ctx *ctx);
int cry_ecdsa_keygen(cry_ecdsa_ctx *ctx);
#ifdef __cplusplus
}
......
......@@ -19,6 +19,7 @@
#define CRY_ECP_GRP_BP256R1 8
#define CRY_ECP_GRP_BP384R1 9
#define CRY_ECP_GRP_BP512R1 10
/**
* EC point
*/
......@@ -31,7 +32,7 @@ struct cry_ecp {
typedef struct cry_ecp cry_ecp;
/*
* EC point group equation parameters
* EC group equation parameters.
* y^2 = (x^3 + ax + b) % p
*/
struct cry_ecp_grp {
......@@ -88,9 +89,9 @@ void cry_ecp_clear_list(cry_ecp *p, ... /* (cry_ecp *)NULL */);
cry_mpi_swap(&(a)->z, &(b)->z); \
} while (0)
int cry_ecp_grp_init(cry_ecp_grp *ec);
int cry_ecp_grp_init(cry_ecp_grp *grp);
void cry_ecp_grp_clear(cry_ecp_grp *ec);
void cry_ecp_grp_clear(cry_ecp_grp *grp);
int cry_ecp_grp_load(cry_ecp_grp *grp, int grp_id);
......
......@@ -11,7 +11,6 @@
#include <stdint.h>
#include <stddef.h>
#define CRY_SHA512_DIGEST_SIZE 64
struct cry_sha512_ctx {
......@@ -64,12 +63,21 @@ void cry_sha512_digest(struct cry_sha512_ctx *ctx, unsigned char *out);
/**
* SHA-512 computation of a given input.
*
* @param out SHA-512 result buffer (shall be at least 32 bytes).
* @param out SHA-512 result buffer (shall be at least 64 bytes).
* @param data Input data buffer.
* @param len Input data length.
*/
void cry_sha512(unsigned char *out, const unsigned char *data, size_t len);
/**
* SHA-384 computation of a given input.
*
* @param out SHA-384 result buffer (shall be at least 48 bytes).
* @param data Input data buffer.
* @param len Input data length.
*/
void cry_sha384(unsigned char *out, const unsigned char *data, size_t len);
#ifdef __cplusplus
}
#endif
......
......@@ -11,7 +11,7 @@
/** Library version minor number */
#define CRY_MINOR 1
/** Library version patch number */
#define CRY_PATCH 0
#define CRY_PATCH 1
/** Library version number */
#define CRY_VERSION (((CRY_MAJOR << 8) | (CRY_MINOR << 8)) | CRY_PATCH)
......
......@@ -5,8 +5,27 @@
#define CHK(exp) CRY_CHK(exp, e)
/*
* c = rand()
* k = (c mod (q-1)) + 1
* Generate a non zero random secret k less than q.
* (i.e. generate a random less than q-1 then add 1).
*
* k = (rand() mod (q-1)) + 1
*
* Is extremely important to don't reuse the same ephemeral key k.
*
* If the ephemeral key k is reused then DSA signature is subject
* to a trivial attack:
*
* If two signatures (r1,s1) and (r2,s2) are generated using the same
* ephemeral key k, then r = r1 = r2.
* (An attacker can easily detect the situation)
*
* The private key d can be easily found:
*
* s1 = (M1 - d*r) * k^-1 (mod q)
* s2 = (M2 - d*r) * k^-1 (mod q)
* s1 - s2 = (M1 - M2) * k^-1 (mod q)
* k = (M1 - M2) / (s1 - s2) (mod q)
* d = (M1 - k*s1) / r (mod q)
*/
static int secret_gen(cry_mpi *k, const cry_mpi *q)
{
......@@ -16,7 +35,7 @@ static int secret_gen(cry_mpi *k, const cry_mpi *q)
one.sign = 0;
one.used = 1;
one.alloc = 1;
one.alloc = 0;
one.data = &dig;
if ((res = cry_mpi_init(&t)) != 0)
......@@ -31,7 +50,7 @@ e: cry_mpi_clear(&t);
return res;
}
int cry_dsa_sign(cry_dsa_ctx *ctx, cry_dsa_signature *sign,
int cry_dsa_sign(cry_dsa_ctx *ctx, cry_dsa_sig *sig,
const unsigned char *in, size_t len)
{
int res;
......@@ -40,32 +59,30 @@ int cry_dsa_sign(cry_dsa_ctx *ctx, cry_dsa_signature *sign,
if ((res = cry_mpi_init_list(&k, &z, (cry_mpi *)NULL)) != 0)
return res;
/* z = input buffer is eventually truncated to the size of q */
if (ctx->q.used * CRY_MPI_DIGIT_BYTES < len)
len = ctx->q.used * CRY_MPI_DIGIT_BYTES;
CHK(cry_mpi_load_bin(&z, in, len));
/* k = c mod (q-1) + 1 */
CHK(secret_gen(&k, &ctx->q));
/* r = (g^k mod p) mod q */
CHK(cry_mpi_mod_exp(&sign->r, &ctx->g, &k, &ctx->p));
CHK(cry_mpi_mod(&sign->r, &sign->r, &ctx->q));
CHK(cry_mpi_mod_exp(&sig->r, &ctx->g, &k, &ctx->p));
CHK(cry_mpi_mod(&sig->r, &sig->r, &ctx->q));
/* z = buf truncated to the size of q */
/* TODO: double check... the book do strange stuff here */
if (ctx->q.used * CRY_MPI_DIGIT_BYTES < len)
len = ctx->q.used * CRY_MPI_DIGIT_BYTES;
CHK(cry_mpi_load_bin(&z, in, len));
/* s = (inv(k) * (z + xr)) mod q */
/* s = (inv(k) * (z + d*r)) mod q */
CHK(cry_mpi_inv(&k, &k, &ctx->q));
CHK(cry_mpi_copy(&sign->s, &ctx->pvt));
CHK(cry_mpi_mul(&sign->s, &sign->s, &sign->r));
CHK(cry_mpi_add(&sign->s, &sign->s, &z));
CHK(cry_mpi_mul(&sign->s, &sign->s, &k));
CHK(cry_mpi_mod(&sign->s, &sign->s, &ctx->q));
CHK(cry_mpi_mul(&sig->s, &ctx->pvt, &sig->r));
CHK(cry_mpi_add(&sig->s, &sig->s, &z));
CHK(cry_mpi_mul(&sig->s, &sig->s, &k));
CHK(cry_mpi_mod(&sig->s, &sig->s, &ctx->q));
e: cry_mpi_clear_list(&k, &z, (cry_mpi *)NULL);
return res;
}
int cry_dsa_verify(cry_dsa_ctx *ctx, const cry_dsa_signature *sign,
int cry_dsa_verify(cry_dsa_ctx *ctx, const cry_dsa_sig *sig,
const unsigned char *in, size_t len)
{
int res;
......@@ -74,21 +91,21 @@ int cry_dsa_verify(cry_dsa_ctx *ctx, const cry_dsa_signature *sign,
if ((res = cry_mpi_init_list(&z, &w, &u1, &u2, (cry_mpi *)NULL)) != 0)
return res;
/* w = inv(s) mod q */
CHK(cry_mpi_copy(&w, &sign->s));
CHK(cry_mpi_inv(&w, &w, &ctx->q));
/* z = buf truncated to the size of q */
/* z = input buffer is eventually truncated to the size of q */
if (ctx->q.used * CRY_MPI_DIGIT_BYTES < len)
len = ctx->q.used * CRY_MPI_DIGIT_BYTES;
CHK(cry_mpi_load_bin(&z, in, len));
/* w = inv(s) mod q */
CHK(cry_mpi_copy(&w, &sig->s));
CHK(cry_mpi_inv(&w, &w, &ctx->q));
/* u1 = (z * w) mod q */
CHK(cry_mpi_mul(&z, &z, &w));
CHK(cry_mpi_mod(&z, &z, &ctx->q));
/* u2 = (r * w) mod q */
CHK(cry_mpi_mul(&w, &sign->r, &w));
CHK(cry_mpi_mul(&w, &sig->r, &w));
CHK(cry_mpi_mod(&w, &w, &ctx->q));
/* v = (((g^u1) mod p * (y^u2) mod p) mod p) mod q */
......@@ -99,20 +116,80 @@ int cry_dsa_verify(cry_dsa_ctx *ctx, const cry_dsa_signature *sign,
CHK(cry_mpi_mod(&u1, &u1, &ctx->q));
/* Check to see if v and sig match */
res = (cry_mpi_cmp_abs(&u1, &sign->r) == 0) ? 0 : -1;
res = (cry_mpi_cmp_abs(&u1, &sig->r) == 0) ? 0 : -1;
e: cry_mpi_clear_list(&z, &w, &u1, &u2, (cry_mpi *)NULL);
return res;
}
int cry_dsa_init(cry_dsa_ctx *ctx)
{
return cry_mpi_init_list(&ctx->p, &ctx->q, &ctx->g, &ctx->pvt, &ctx->pvt,
return cry_mpi_init_list(&ctx->p, &ctx->q, &ctx->g, &ctx->pub, &ctx->pvt,
(cry_mpi *)NULL);
}
void cry_dsa_clear(cry_dsa_ctx *ctx)
{
cry_mpi_clear_list(&ctx->p, &ctx->q, &ctx->g, &ctx->pvt, &ctx->pvt,
cry_mpi_clear_list(&ctx->p, &ctx->q, &ctx->g, &ctx->pub, &ctx->pvt,
(cry_mpi *)NULL);
cry_memset(ctx, 0, sizeof(*ctx));
}
#define ITER_MAX_OUT 1024
#define ITER_MAX_IN 4096
/*
* Assume l=8
* 1. Generate a random prime q such that 2^150 < q < 2^160
* 2. Generate a random integer M with 2^1023 < M < 2^1024
* 3. Mr = M (mod 2q)
* 4. p-1 = M-Mr (mod 2q) (note that M-Mr is a multiple of 2q, thus is even)
* 5. If p is prime return (p,q) else repeat from 2.
* The entire algorithm is repeated at most ITER_MAX_OUT times.
*/
int cry_dsa_keygen(cry_dsa_ctx *ctx, unsigned int l)
{
int res = -1;
cry_mpi p1, q, r, one;
unsigned int i, j;
cry_mpi_init_list(&p1, &q, &r, &one, NULL);
CHK(cry_mpi_set_int(&one, 1));
for (i = 0; i < ITER_MAX_OUT; i++) {
/* Generate a 160-bit prime q */
CHK(cry_mpi_prime(&ctx->q, 160, NULL));
/* Generate a prime p betweeb 512 and 1024 bits such that q | (p-1) */
for (j = 0; j < ITER_MAX_IN; j++) {
CHK(cry_mpi_rand(&ctx->p, 512 + l*64));
CHK(cry_mpi_add(&r, &ctx->q, &ctx->q));
CHK(cry_mpi_mod(&r, &ctx->p, &r));
CHK(cry_mpi_sub(&ctx->p, &ctx->p, &r));
CHK(cry_mpi_add(&ctx->p, &ctx->p, &one));
if (cry_mpi_is_prime(&ctx->p))
break;
}
if (j == ITER_MAX_IN)
continue; /* Retry */
/* Select a generator g of the unique cyclic group of order q in Zp */
CHK(cry_mpi_sub(&p1, &ctx->p, &one));
CHK(cry_mpi_div(&q, NULL, &p1, &ctx->q));
CHK(cry_mpi_sub(&p1, &ctx->p, &one)); /* Required? */
for (j = 0; j < ITER_MAX_IN; j++) {
/* Get a random in Zp\{0} */
CHK(cry_mpi_rand_range(&r, &p1));
CHK(cry_mpi_add(&r, &r, &one));
CHK(cry_mpi_mod_exp(&ctx->g, &r, &q, &ctx->p));
if (cry_mpi_cmp_abs(&ctx->g, &one) > 0)
break;
}
if (j == ITER_MAX_IN)
continue; /* Retry */
/* Finally compute public and public keys */
cry_mpi_rand_range(&ctx->pvt, &q);
cry_mpi_mod_exp(&ctx->pub, &ctx->g, &ctx->pvt, &ctx->p);
res = 0;
break;
}
e: cry_mpi_clear_list(&p1, &q, &r, &one, NULL);
return res;
}
#include <cry/ecdsa.h>
#include "mpi/mpi_pvt.h"
#define CHK0(exp) CRY_CHK(exp, e0)
#define CHK1(exp) CRY_CHK(exp, e1)
#define CHK0(exp) CRY_CHK(res = (exp), e0)
#define CHK1(exp) CRY_CHK(res = (exp), e1)
int cry_ecdsa_sign(cry_ecdsa_ctx *ctx, cry_ecdsa_signature *sign,
int cry_ecdsa_sign(cry_ecdsa_ctx *ctx, cry_ecdsa_sig *sig,
const unsigned char *in, size_t len)
{
int res;
......@@ -13,9 +13,13 @@ int cry_ecdsa_sign(cry_ecdsa_ctx *ctx, cry_ecdsa_signature *sign,
if ((res = cry_mpi_init_list(&k, &z, (cry_mpi *)NULL)) != 0)
return res;
CHK0(cry_ecp_init(&X));
/* z = input buffer is eventually truncated to the size of q */
if (ctx->grp.n.used * CRY_MPI_DIGIT_BYTES < len)
len = ctx->grp.n.used * CRY_MPI_DIGIT_BYTES;
CHK1(cry_mpi_load_bin(&z, in, len));
/* This should be a random number between 0 and n-1 */
#if 0
unsigned char K[] = {
......@@ -25,36 +29,27 @@ int cry_ecdsa_sign(cry_ecdsa_ctx *ctx, cry_ecdsa_signature *sign,
};
CHK1(cry_mpi_load_bin(&k, K, sizeof(K)));
#else
CHK1(cry_mpi_rand_range(&k, &ctx->ec.n));
CHK1(cry_mpi_rand_range(&k, &ctx->grp.n));
#endif
CHK1(cry_mpi_copy(&X.x, &ctx->ec.g.x));
CHK1(cry_mpi_copy(&X.y, &ctx->ec.g.y));
CHK1(cry_ecp_mul(&X, &X, &k, &ctx->ec));
CHK1(cry_ecp_mul(&X, &ctx->grp.g, &k, &ctx->grp));
/* r = x mod n */
CHK1(cry_mpi_mod(&sign->r, &X.x, &ctx->ec.n));
/* z is the L_n leftmost bits of hash - cannot be longer than n */
if (ctx->ec.n.used * CRY_MPI_DIGIT_BYTES < len)
len = ctx->ec.n.used * CRY_MPI_DIGIT_BYTES;
CHK1(cry_mpi_load_bin(&z, in, len));
cry_mpi_swap(&sig->r, &X.x);
/* s = (inv(k) * (z + r*d_a)) mod n */
CHK1(cry_mpi_inv(&k, &k, &ctx->ec.n));
CHK1(cry_mpi_copy(&sign->s, &ctx->d));
CHK1(cry_mpi_mul(&sign->s, &sign->s, &sign->r));
CHK1(cry_mpi_add(&sign->s, &sign->s, &z));
CHK1(cry_mpi_mul(&sign->s, &sign->s, &k));
CHK1(cry_mpi_mod(&sign->s, &sign->s, &ctx->ec.n));
/* s = (inv(k) * (z + r*d)) mod n */
CHK1(cry_mpi_inv(&k, &k, &ctx->grp.n));
CHK1(cry_mpi_mul(&sig->s, &ctx->d, &sig->r));
CHK1(cry_mpi_add(&sig->s, &sig->s, &z));
CHK1(cry_mpi_mul(&sig->s, &sig->s, &k));
CHK1(cry_mpi_mod(&sig->s, &sig->s, &ctx->grp.n));
e1: cry_ecp_clear(&X);
e0: cry_mpi_clear_list(&k, &z, (cry_mpi *)NULL);
return 0;
}
int cry_ecdsa_verify(cry_ecdsa_ctx *ctx, const cry_ecdsa_signature *sign,
int cry_ecdsa_verify(cry_ecdsa_ctx *ctx, const cry_ecdsa_sig *sig,
const unsigned char *in, size_t len)
{
int res;
......@@ -63,46 +58,72 @@ int cry_ecdsa_verify(cry_ecdsa_ctx *ctx, const cry_ecdsa_signature *sign,
if ((res = cry_mpi_init_list(&z, &w, (cry_mpi *)NULL)) != 0)
return res;
CHK0(cry_ecp_init_list(&G, &Q, (cry_ecp *)NULL));
/* w = inv(s) mod n */
CHK1(cry_mpi_copy(&w, &sign->s));
CHK1(cry_mpi_inv(&w, &w, &ctx->ec.n));
/* z is the L_n leftmost bits of the hash, eventually truncate */
if (ctx->ec.n.used * CRY_MPI_DIGIT_BYTES < len)
len = ctx->ec.n.used * CRY_MPI_DIGIT_BYTES;
/* z = input buffer is eventually truncated to the size of q */
if (ctx->grp.n.used * CRY_MPI_DIGIT_BYTES < len)
len = ctx->grp.n.used * CRY_MPI_DIGIT_BYTES;
CHK1(cry_mpi_load_bin(&z, in, len));
/* w = inv(s) mod n */
CHK1(cry_mpi_copy(&w, &sig->s));
CHK1(cry_mpi_inv(&w, &w, &ctx->grp.n));
/* u1 = (z * w) mod n */
CHK1(cry_mpi_mul(&z, &z, &w));
CHK1(cry_mpi_mod(&z, &z, &ctx->ec.n));
CHK1(cry_mpi_mod(&z, &z, &ctx->grp.n));
/* u2 = (r * w) mod n */
CHK1(cry_mpi_mul(&w, &sign->r, &w));
CHK1(cry_mpi_mod(&w, &w, &ctx->ec.n));
CHK1(cry_mpi_mul(&w, &sig->r, &w));
CHK1(cry_mpi_mod(&w, &w, &ctx->grp.n));
/* (x1, y1) = u1 * G + u2 * Q */
CHK1(cry_ecp_mul(&G, &ctx->ec.g, &z, &ctx->ec));
CHK1(cry_ecp_mul(&Q, &ctx->q, &w, &ctx->ec));
CHK1(cry_ecp_add(&G, &G, &Q, &ctx->ec));
CHK1(cry_ecp_mul(&G, &ctx->grp.g, &z, &ctx->grp));
CHK1(cry_ecp_mul(&Q, &ctx->q, &w, &ctx->grp));
CHK1(cry_ecp_add(&G, &G, &Q, &ctx->grp));
/* r = x1 mod n */
CHK1(cry_mpi_mod(&G.x, &G.x, &ctx->ec.n));
CHK1(cry_mpi_mod(&G.x, &G.x, &ctx->grp.n)); // inutile
res = (cry_mpi_cmp_abs(&G.x, &sign->r) == 0) ? 0 : -1;
res = (cry_mpi_cmp_abs(&G.x, &sig->r) == 0) ? 0 : -1;
e1: cry_ecp_clear_list(&G, &Q, (cry_ecp *)NULL);
e0: cry_mpi_clear_list(&z, &w, &G.x, &G.y, &Q.x, &Q.y, (cry_mpi *)NULL);
return res;
}
int cry_ecdsa_keygen(const cry_ecp_grp *ec, cry_mpi *d, cry_ecp *q)
int cry_ecdsa_init(cry_ecdsa_ctx *ctx, int grp_id)
{
int res;
res = cry_mpi_init(&ctx->d);
if (res != 0)
return res;
CHK0(cry_ecp_init(&ctx->q));
if (grp_id != -1)
CHK1(cry_ecp_grp_load(&ctx->grp, grp_id));
else
CHK1(cry_ecp_grp_init(&ctx->grp));
return 0;
e1: cry_ecp_clear(&ctx->q);
e0: cry_mpi_clear(&ctx->d);
return res;
}
void cry_ecdsa_clear(cry_ecdsa_ctx *ctx)
{
cry_mpi_clear(&ctx->d);
cry_ecp_clear(&ctx->q);
cry_ecp_grp_clear(&ctx->grp);
cry_memset(ctx, 0, sizeof(*ctx));
}
int cry_ecdsa_keygen(cry_ecdsa_ctx *ctx)
{
int res;
if ((res = cry_mpi_rand_range(d, &ec->p)) == 0)
res = cry_ecp_mul(q, &ec->g, d, ec);
if ((res = cry_mpi_rand_range(&ctx->d, &ctx->grp.n)) == 0)
res = cry_ecp_mul(&ctx->q, &ctx->grp.g, &ctx->d, &ctx->grp);
return res;
}
......@@ -8,6 +8,27 @@
/*
* Generate a random secret k, such that gcd(k, p-1) = 1
* (should be invertible modulo p-1).
*
* Is extremely important to don't reuse the same ephemeral key k.
*
* If the ephemeral key K is reused then Elgamal signature is subject
* to a trivial attack:
*
* If two signatures (r1,s1) and (r2,s2) are generated using the same
* ephemeral key k, then r = r1 = r2.
* (An attacker can easily detect the situation)
*
* The private key d can be easily found:
*
* s1 = (M1 - d*r) * k^-1 (mod p-1)
* s2 = (M2 - d*r) * k^-1 (mod p-1)
* s1 - s2 = (M1 - M2) * k^-1 (mod p-1)
* k = (M1 - M2) / (s1 - s2) (mod p-1)
* d = (M1 - k*s1) / r (mod p-1)
*
* Note: if gcd(s1-s2, p-1) <> 1 then there are multiple solutions and the
* attacker needs to check for the correct one (not a big issue for him).
*/
static int secret_gen(cry_mpi *k, const cry_mpi *t, const cry_mpi *one)
{
......
......@@ -176,6 +176,7 @@ static int encrypt(cry_rsa_ctx *ctx, unsigned char **out, size_t *outlen,
{
int res;
size_t mod_siz, block_siz;
void *newptr;
*out = NULL;
*outlen = 0;
......@@ -186,11 +187,12 @@ static int encrypt(cry_rsa_ctx *ctx, unsigned char **out, size_t *outlen,
if (inlen < block_siz)
block_siz = inlen;
*out = realloc(*out, *outlen + mod_siz);
if (*out == NULL) {
newptr = realloc(*out, *outlen + mod_siz);
if (newptr == NULL) {
res = -1;
break;
}
*out = newptr;
res = encrypt_block(ctx, *out + *outlen, in, block_siz, sign);
if (res != 0)
......@@ -216,6 +218,7 @@ static int decrypt(cry_rsa_ctx *ctx, unsigned char **out, size_t *outlen,
{
int res;
size_t mod_siz;
void *newptr;
*out = NULL;
*outlen = 0;
......@@ -228,7 +231,12 @@ static int decrypt(cry_rsa_ctx *ctx, unsigned char **out, size_t *outlen,
break;
}
*out = realloc(*out, *outlen + mod_siz);
newptr = realloc(*out, *outlen + mod_siz);
if (newptr == NULL) {
res = -1;
break;
}
*out = newptr;
res = decrypt_block(ctx, *out, in, mod_siz, sign);
if (res < 0)
......
......@@ -24,6 +24,7 @@ int cry_ecp_add(cry_ecp *pr, const cry_ecp *p1, const cry_ecp *p2,
CHK0(cry_mpi_mod(&num, &num, &grp->p));
CHK0(cry_mpi_sub(&den, &p2->x, &p1->x)); /* den = x2 - x1 */
CHK0(cry_mpi_mod(&den, &den, &grp->p));
/*
* If x1=x2 then:
* - if y1=y2 obviously p1=p2
......@@ -43,14 +44,17 @@ int cry_ecp_add(cry_ecp *pr, const cry_ecp *p1, const cry_ecp *p2,
CHK0(cry_mpi_init_list(&lam, &r.x, &r.y, &r.z, (cry_mpi *)NULL));
CHK1(cry_mpi_inv(&den, &den, &grp->p)); /* den^(-1) (mod p) */
CHK1(cry_mpi_mul(&lam, &num, &den)); /* lam = num / den */
CHK1(cry_mpi_mod(&lam, &lam, &grp->p));
CHK1(cry_mpi_sqr(&r.x, &lam)); /* x = lam^2 */
CHK1(cry_mpi_mod(&r.x, &r.x, &grp->p));
CHK1(cry_mpi_sub(&r.x, &r.x, &p1->x)); /* x = lam^2 - x1 */
CHK1(cry_mpi_sub(&r.x, &r.x, &p2->x)); /* x = lam^2 - x1 - x2 */
CHK1(cry_mpi_mod(&r.x, &r.x, &grp->p)); /* x = (lam^2 - x1 - x2) % p */
CHK1(cry_mpi_sub(&r.y, &p1->x, &r.x)); /* y = x1 - x */
CHK1(cry_mpi_mul(&r.y, &r.y, &lam)); /* y = (x1 - x) * lam */
CHK1(cry_mpi_mod(&r.y, &r.y, &grp->p));
CHK1(cry_mpi_sub(&r.y, &r.y, &p1->y)); /* y = (x1 - x) * lam - y1 */
CHK1(cry_mpi_mod(&r.y, &r.y, &grp->p)); /* y = ((x1 - x) * lam - y1) % p */
......
......@@ -42,21 +42,21 @@ int cry_ecp_copy(cry_ecp *d, const cry_ecp *s)
}
int cry_ecp_grp_init(cry_ecp_grp *ec)
int cry_ecp_grp_init(cry_ecp_grp *grp)
{
int res;
res = cry_mpi_init_list(&ec->p, &ec->a, &ec->b, &ec->n,
&ec->g.x, &ec->g.y, &ec->g.z,
res = cry_mpi_init_list(&grp->p, &grp->a, &grp->b, &grp->n,
&grp->g.x, &grp->g.y, &grp->g.z,
(cry_mpi *)NULL);
if (res == 0)
cry_ecp_set_zero(&ec->g);
cry_ecp_set_zero(&grp->g);
return res;
}
void cry_ecp_grp_clear(cry_ecp_grp *ec)
void cry_ecp_grp_clear(cry_ecp_grp *grp)
{
cry_mpi_clear_list(&ec->p, &ec->a, &ec->b, &ec->n,
&ec->g.x, &ec->g.y, &ec->g.z,
cry_mpi_clear_list(&grp->p, &grp->a, &grp->b, &grp->n,
&grp->g.x, &grp->g.y, &grp->g.z,
(cry_mpi *)NULL);
}
......@@ -118,7 +118,7 @@ static const cry_mpi_digit secp224r1_p[] = {
BYTES_TO_DIGITS_8(0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00),
BYTES_TO_DIGITS_8(0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF),
BYTES_TO_DIGITS_8(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF),
BYTES_TO_DIGITS_8(0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00),
BYTES_TO_DIGITS_4(0xFF, 0xFF, 0xFF, 0xFF),
};
#define secp224r1_a NULL
......@@ -621,21 +621,20 @@ static void ecp_grp_load(cry_ecp_grp *grp,
const cry_mpi_digit *gy, size_t gylen,
const cry_mpi_digit *n, size_t nlen)
{
static const cry_mpi_digit one = 0x01;
static const cry_mpi_digit three = 0x03;
ecp_mpi_load(&grp->p, p, plen);
if (a != NULL) {
ecp_mpi_load(&grp->a, a, alen);
} else {
grp->a.data = (cry_mpi_digit *)&three;
grp->a.alloc = 1;
grp->a.used = 1;
grp->a.sign = 1;
ecp_mpi_load(&grp->a, &three, sizeof(three));
grp->a.sign = 1;
}
ecp_mpi_load(&grp->b, b, blen);
ecp_mpi_load(&grp->g.x, gx, gxlen);
ecp_mpi_load(&grp->g.y, gy, gylen);
(void)cry_mpi_init_size(&grp->g.z, 0);
ecp_mpi_load(&grp->g.z, &one, sizeof(one));
ecp_mpi_load(&grp->n, n, nlen);
}
......
......@@ -20,21 +20,27 @@ int cry_ecp_dbl(cry_ecp *pr, const cry_ecp *p1, const cry_ecp_grp *grp)
CHK(cry_mpi_set_int(&num, 3)); /* num = 3 */
CHK(cry_mpi_mul(&num, &num, &p1->x)); /* num = 3 * x1 */
CHK(cry_mpi_mul(&num, &num, &p1->x)); /* num = 3 * x1^2 */
CHK(cry_mpi_mod(&num, &num, &grp->p));
CHK(cry_mpi_add(&num, &num, &grp->a)); /* num = 3 * x1^2 + a */
CHK(cry_mpi_mod(&num, &num, &grp->p));
CHK(cry_mpi_set_int(&den, 2)); /* den = 2 */
CHK(cry_mpi_mul(&den, &den, &p1->y)); /* den = 2 * y1 */
CHK(cry_mpi_inv(&den, &den, &grp->p)); /* den = (2 * y1)^(-1) (mod p) */
CHK(cry_mpi_mod(&den, &den, &grp->p));
CHK(cry_mpi_mul(&lam, &num, &den)); /* lam = num / den */
CHK(cry_mpi_mod(&den, &den, &grp->p));
CHK(cry_mpi_sqr(&r.x, &lam)); /* x = lam^2 */
CHK(cry_mpi_mod(&r.x, &r.x, &grp->p));
CHK(cry_mpi_sub(&r.x, &r.x, &p1->x)); /* x = lam^2 - x1 */
CHK(cry_mpi_sub(&r.x, &r.x, &p1->x)); /* x = lam^2 - 2*x1 */
CHK(cry_mpi_mod(&r.x, &r.x, &grp->p)); /* x = (lam^2 - 2*x1) % p */
CHK(cry_mpi_sub(&r.y, &p1->x, &r.x)); /* y = x1 - x */
CHK(cry_mpi_mul(&r.y, &r.y, &lam)); /* y = (x1 - x) * lam */
CHK(cry_mpi_mod(&r.y, &r.y, &grp->p));
CHK(cry_mpi_sub(&r.y, &r.y, &p1->y)); /* y = (x1 - x) * lam - y1 */
CHK(cry_mpi_mod(&r.y, &r.y, &grp->p)); /* y = ((x1 - x) * lam - y1) % p */
......
......@@ -227,3 +227,23 @@ void cry_sha512_digest(cry_sha512_ctx *ctx, unsigned char *out)
CRY_WRITE64_BE(ctx->state[7], out + 56);
}
}
void cry_sha512(unsigned char *out, const unsigned char *data, size_t len)
{
cry_sha512_ctx ctx;
cry_sha512_init(&ctx, 0);
cry_sha512_update(&ctx, data, len);
cry_sha512_digest(&ctx, out);
cry_sha512_clear(&ctx);
}
void cry_sha384(unsigned char *out, const unsigned char *data, size_t len)
{
cry_sha512_ctx ctx;
cry_sha512_init(&ctx, 1);
cry_sha512_update(&ctx, data, len);
cry_sha512_digest(&ctx, out);
cry_sha512_clear(&ctx);
}
......@@ -11,6 +11,8 @@
/** Nop to prevent some warnings */
#define NOP do {} while (0)
#define CRY_UNUSED(v) (void)(v)
/** Statically get array number of elements */
#define CRY_ARRAY_LEN(ar) (sizeof(ar)/sizeof((ar)[0]))
......
......@@ -119,10 +119,12 @@ int cry_mpi_get_int(cry_mpi *a, long *val)
void cry_mpi_clear(cry_mpi *a)
{
if (a->data != NULL)
free(a->data);
if (a->data != NULL) {
if (a->alloc != 0) /* do not free non malloced data */
free(a->data);
a->data = NULL;
}
/* reset the members to make debugging easier */
a->data = NULL;
a->alloc = 0;
a->used = 0;
a->sign = 0;
......
......@@ -26,14 +26,15 @@ objects := \
md5_test.o \
sha1_test.o \
sha256_test.o \
sha512_test.o \
ecp_test.o \
elgamal_test.o \
dsa_test.o \
ecdsa_test.o \
utils_test.o
# rand_test.o \
dh_test.o \
dsa_test.o \
ecdsa_test.o \
ecdh_test.o \
.PHONY: all clean
......
#include "test.h"
#include <cry/dsa.h>
static cry_dsa_ctx dsa;
static cry_dsa_sig sig;
static const unsigned char sha[] = {
0x97, 0x7f, 0x2b, 0x13, 0xa2, 0xc3, 0x46, 0x38,
0x23, 0x35, 0x95, 0x6e, 0xa6, 0xc7, 0x5a, 0xf1,
0xd0, 0x13, 0xad, 0xb4, 0x07, 0xa2, 0xa3, 0x30,
0x20, 0xa8, 0x5f, 0x18, 0x78, 0x9f, 0xa1, 0x43,
};
static void keygen(unsigned int l)
{
ASSERT_OK(cry_dsa_keygen(&dsa, l));
ASSERT_OK(cry_dsa_sign(&dsa, &sig, sha, sizeof(sha)));
ASSERT_OK(cry_dsa_verify(&dsa, &sig, sha, sizeof(sha)));
}
static void keygen_512(void)
{
keygen(0);
}
static void keygen_768(void)
{
#ifndef SKIP_SLOW
keygen(4);
#else
TRACE2(" (skip)\n");
#endif
}
static void keygen_1024(void)
{
#ifndef SKIP_SLOW
keygen(8);
#else
TRACE2(" (skip)\n");
#endif
}
static const unsigned char pvt[] = {
0x53, 0x61, 0xae, 0x4f, 0x6f, 0x25, 0x98, 0xde,
0xc4, 0xbf, 0x0b, 0xbe, 0x09, 0x5f, 0xdf, 0x90,
......@@ -47,29 +88,38 @@ static const unsigned char G[] = {
0x99, 0xd8, 0xa8, 0x19, 0x96, 0xf7, 0x7f, 0x99
};
static const unsigned char *msg = "abc123";
void dsa_test(void)
static void sign_verify(void)
{
cry_dsa_ctx dsa;
cry_dsa_signature sign;
ASSERT_OK(cry_mpi_load_bin(&dsa.g, G, sizeof(G)));
ASSERT_OK(cry_mpi_load_bin(&dsa.p, P, sizeof(P)));
ASSERT_OK(cry_mpi_load_bin(&dsa.q, Q, sizeof(Q)));
ASSERT_OK(cry_mpi_load_bin(&dsa.pvt, pvt, sizeof(pvt)));
ASSERT_OK(cry_mpi_load_bin(&dsa.pub, pub, sizeof(pub)));
ASSERT_OK(cry_mpi_init_list(&sign.r, &sign.s, NULL));
ASSERT_OK(cry_mpi_init_bin(&dsa.g, G, sizeof(G)));
ASSERT_OK(cry_mpi_init_bin(&dsa.p, P, sizeof(P)));
ASSERT_OK(cry_mpi_init_bin(&dsa.q, Q, sizeof(Q)));
ASSERT_OK(cry_mpi_init_bin(&dsa.pvt, pvt, sizeof(pvt)));
ASSERT_OK(cry_mpi_init_bin(&dsa.pub, pub, sizeof(pub)));
ASSERT_OK(cry_dsa_sign(&dsa, &sig, sha, sizeof(sha)));
ASSERT_OK(cry_dsa_verify(&dsa, &sig, sha, sizeof(sha)));
}
ASSERT_OK(cry_dsa_sign(&dsa, &sign, msg, strlen(msg)));
static void setup(void)
{
cry_dsa_init(&dsa);
cry_mpi_init_list(&sig.r, &sig.s, NULL);
}
TRACE("DSA signature of '%s' is:\n", msg);
PRINT_MPI("r", &sign.r, 16);
PRINT_MPI("s", &sign.s, 16);
static void teardown(void)
{
cry_dsa_clear(&dsa);
cry_mpi_clear_list(&sig.r, &sig.s, NULL);
}
ASSERT_OK(cry_dsa_verify(&dsa, &sign, msg, strlen(msg)));
#define MYRUN(name, test) run(name, test, setup, teardown)
cry_mpi_clear_list(&sign.r, &sign.s,
&dsa.g, &dsa.p, &dsa.q,
&dsa.pvt, &dsa.pub, NULL);
void dsa_test(void)
{
TRACE("* DSA\n");
MYRUN("Keygen 512", keygen_512);
MYRUN("Keygen 768", keygen_768);
MYRUN("Keygen 1024", keygen_1024);
MYRUN("Sign and verify", sign_verify);
TRACE("\n");
}
#include "test.h"
#include <cry/ecdsa.h>
static cry_ecdsa_ctx ecdsa;
static cry_ecdsa_sig sig;
/* key */
static const unsigned char d_dat[] = {
0xDC, 0x51, 0xD3, 0x86, 0x6A, 0x15, 0xBA, 0xCD,
0xE3, 0x3D, 0x96, 0xF9, 0x92, 0xFC, 0xA9, 0x9D,
0xA7, 0xE6, 0xEF, 0x09, 0x34, 0xE7, 0x09, 0x75,
0x59, 0xC2, 0x7F, 0x16, 0x14, 0xC8, 0x8A, 0x7F
0x16, 0x79, 0x7b, 0x5c, 0x0c, 0x7e, 0xd5, 0x46,
0x1e, 0x2f, 0xf1, 0xb8, 0x8e, 0x6e, 0xaf, 0xa0,
0x3c, 0x0f, 0x46, 0xbf, 0x07, 0x20, 0x00, 0xdf,
0xc8, 0x30, 0xd6, 0x15,
};
static const unsigned char *msg = "Hello World";
static const unsigned char sha[] = {
0x69, 0x93, 0x25, 0xd6, 0xfc, 0x8f, 0xbb, 0xb4,
0x98, 0x1a, 0x6d, 0xed, 0x3c, 0x3a, 0x54, 0xad,
0x2e, 0x4e, 0x3d, 0xb8, 0xa5, 0x66, 0x92, 0x01,
0x91, 0x20, 0x64, 0xc6, 0x4e, 0x70, 0x0c, 0x13,
0x92, 0x48, 0xcd, 0xc1,
};
void ecdsa_test(void)
static void sign_verify(void)
{
cry_ecdsa_ctx ecdsa;
cry_ecdsa_signature sign;
/* Load a well known curve params */
cry_ecp_grp_clear(&ecdsa.grp);
ASSERT_OK(cry_ecp_grp_load(&ecdsa.grp, CRY_ECP_GRP_SECP224R1));
#if 0
ASSERT_OK(cry_ecdsa_keygen(&ecdsa.grp, &ecdsa.d, &ecdsa.q));
#else
cry_mpi_load_bin(&ecdsa.d, d_dat, sizeof(d_dat));
cry_ecp_mul(&ecdsa.q, &ecdsa.grp.g, &ecdsa.d, &ecdsa.grp);
#endif
ASSERT_OK(cry_ecdsa_sign(&ecdsa, &sig, sha, sizeof(sha)));
#if 0
PRINT_MPI("p", &ecdsa.grp.p, 16);
PRINT_MPI("a", &ecdsa.grp.a, 16);
PRINT_MPI("b", &ecdsa.grp.b, 16);
PRINT_MPI("g.x", &ecdsa.grp.g.x, 16);
PRINT_MPI("g.y", &ecdsa.grp.g.y, 16);
PRINT_MPI("n", &ecdsa.grp.n, 16);
PRINT_MPI("d", &ecdsa.d, 16);
PRINT_MPI("q.x", &ecdsa.q.x, 16);
PRINT_MPI("q.y", &ecdsa.q.y, 16);
PRINT_MPI("r", &sig.r, 16);
PRINT_MPI("s", &sig.s, 16);
#endif
ASSERT_OK(cry_ecdsa_verify(&ecdsa, &sig, sha, sizeof(sha)));
}
ASSERT_OK(cry_mpi_init_list(&sign.r, &sign.s, NULL));
static void sign_verify_small(void)
{
unsigned char v = 26;
/* Load a well known curve params */
ASSERT_OK(cry_ec_init_nist_p256(&ecdsa.ec));
cry_mpi_set_int(&ecdsa.grp.p, 17);
cry_mpi_set_int(&ecdsa.grp.a, 2);
cry_mpi_set_int(&ecdsa.grp.b, 10);
cry_mpi_set_int(&ecdsa.grp.n, 19);
cry_mpi_set_int(&ecdsa.grp.g.x, 5);
cry_mpi_set_int(&ecdsa.grp.g.y, 1);
cry_mpi_set_int(&ecdsa.grp.g.z, 1);
/* Generate new public key from private key w and point G */
// cry_mpi_load_bin(&ecdsa.d, d_dat, sizeof(d_dat));
ASSERT_OK(cry_ecp_init(&ecdsa.q));
ASSERT_OK(cry_mpi_init(&ecdsa.d));
ASSERT_OK(cry_ecdsa_keygen(&ecdsa.ec, &ecdsa.d, &ecdsa.q));
#if 0
ASSERT_OK(cry_ecdsa_keygen(&ecdsa.grp, &ecdsa.d, &ecdsa.q));
#else
cry_mpi_set_int(&ecdsa.d, 7);
cry_ecp_mul(&ecdsa.q, &ecdsa.grp.g, &ecdsa.d, &ecdsa.grp);
#endif
ASSERT_OK(cry_ecdsa_sign(&ecdsa, &sign, msg, strlen(msg)));
PRINT_MPI("r", &sign.r, 16);
PRINT_MPI("s", &sign.s, 16);
ASSERT_OK(cry_ecdsa_sign(&ecdsa, &sig, &v, 1));
ASSERT_OK(cry_ecdsa_verify(&ecdsa, &sig, &v, 1));
}
ASSERT_OK(cry_ecdsa_verify(&ecdsa, &sign, msg, strlen(msg)));
cry_mpi_clear_list(&sign.r, &sign.s, NULL);
/* TODO: release ecdsa context data */
static void setup(void)
{
cry_ecdsa_init(&ecdsa, -1);
cry_mpi_init_list(&sig.r, &sig.s, NULL);
}
static void teardown(void)
{
cry_ecdsa_clear(&ecdsa);
cry_mpi_clear_list(&sig.r, &sig.s, NULL);
}
#define MYRUN(name, test) run(name, test, setup, teardown)
void ecdsa_test(void)
{
TRACE("* ECDSA\n");
MYRUN("Sign and verify (trivially small)", sign_verify_small);
MYRUN("Sign and verify", sign_verify);
TRACE("\n");
}
#include "test.h"
#include <cry/ecp.h>
static cry_ecp_grp grp;
static cry_mpi k;
static cry_ecp P, Q, Q1;
/*
* y^2 = x^3 + 2x + 2 (mod 17)
*
......@@ -39,44 +43,36 @@ static void point_check(const cry_ecp *p, const cry_ecp_grp *grp)
cry_mpi_clear_list(&v, &t, NULL);
}
/* Run through the whole group elements */
static void add_test(void)
{
cry_ecp_grp grp;
cry_ecp p;
int i = 0;
simple_curve_init(&grp);
cry_ecp_init(&p);
cry_ecp_init(&P);
do {
//TRACE("n = %d\n", i);
//cry_mpi_print(&p.x, 10);
//cry_mpi_print(&p.y, 10);
//cry_mpi_print(&p.z, 10);
point_check(&p, &grp);
//TRACE("--------------------\n");
cry_ecp_add(&p, &p, &grp.g, &grp);
point_check(&P, &grp);
cry_ecp_add(&P, &P, &grp.g, &grp);
i++;
} while (!cry_ecp_is_zero(&p));
} while (!cry_ecp_is_zero(&P));
cry_ecp_grp_clear(&grp);
cry_ecp_clear(&p);
cry_ecp_clear(&P);
}
static void mul_test(void)
{
cry_ecp_grp grp;
cry_ecp p;
cry_mpi v;
simple_curve_init(&grp);
cry_ecp_init_int(&p, 9, 16); /* p = 5g = (9, 16) */
cry_ecp_init_int(&P, 9, 16); /* p = 5g = (9, 16) */
cry_mpi_init_int(&v, 2);
point_check(&p, &grp);
cry_ecp_mul(&p, &p, &v, &grp); /* 2p = 10g = (7,11) */
point_check(&p, &grp);
point_check(&P, &grp);
cry_ecp_mul(&P, &P, &v, &grp); /* 2p = 10g = (7,11) */
point_check(&P, &grp);
cry_ecp_grp_clear(&grp);
cry_ecp_clear(&p);
cry_ecp_clear(&P);
cry_mpi_clear(&v);
}
......@@ -216,11 +212,171 @@ static void curve_params_load(void)
RUN(bad_curve_load_test);
}
static int load_args(int argc, char *argv[])
{
int res;
if ((res = cry_mpi_load_str(&k, 16, argv[0])) < 0)
return res;
if ((res = cry_mpi_load_str(&Q.x, 16, argv[1])) < 0)
return res;
if ((res = cry_mpi_load_str(&Q.y, 16, argv[2])) < 0)
return res;
cry_mpi_set_int(&Q.z, 1);
return res;
}
static void mul_test2(int argc, char *argv[])
{
int res;
ASSERT_EQ(argc, 3);
load_args(argc, argv);
res = cry_ecp_mul(&Q1, &P, &k, &grp);
ASSERT_EQ(res, 0);
ASSERT(cry_mpi_cmp(&Q.x, &Q1.x) == 0);
ASSERT(cry_mpi_cmp(&Q.y, &Q1.y) == 0);
ASSERT(cry_mpi_cmp(&Q.z, &Q1.z) == 0);
}
static void secp192r1_set_start_point(void)
{
const char *x = "188DA80EB03090F67CBF20EB43A18800F4FF0AFD82FF1012";
const char *y = "07192B95FFC8DA78631011ED6B24CDD573F977A11E794811";
cry_mpi_load_str(&P.x, 16, x);
cry_mpi_load_str(&P.y, 16, y);
cry_mpi_set_int(&P.z, 1);
}
#ifndef SKIP_SLOW
static void secp224r1_set_start_point(void)
{
const char *x = "B70E0CBD6BB4BF7F321390B94A03C1D356C21122343280D6115C1D21";
const char *y = "BD376388B5F723FB4C22DFE6CD4375A05A07476444D5819985007E34";
cry_mpi_load_str(&P.x, 16, x);
cry_mpi_load_str(&P.y, 16, y);
cry_mpi_set_int(&P.z, 1);
}
#endif
#ifndef SKIP_SLOW
static void secp256r1_set_start_point(void)
{
const char *x =
"6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296";
const char *y =
"4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5";
cry_mpi_load_str(&P.x, 16, x);
cry_mpi_load_str(&P.y, 16, y);
cry_mpi_set_int(&P.z, 1);
}
#endif
#ifndef SKIP_SLOW
static void secp384r1_set_start_point(void)
{
const char *x =
"AA87CA22BE8B05378EB1C71EF320AD746E1D3B628BA79B9859F741E082542A385502F25DBF55296C3A545E3872760AB7";
const char *y =
"3617DE4A96262C6F5D9E98BF9292DC29F8F41DBD289A147CE9DA3113B5F0B8C00A60B1CE1D7E819D7A431D7C90EA0E5F";
cry_mpi_load_str(&P.x, 16, x);
cry_mpi_load_str(&P.y, 16, y);
cry_mpi_set_int(&P.z, 1);
}
#endif
#ifndef SKIP_SLOW
static void secp521r1_set_start_point(void)
{
const char *x =
"00C6858E06B70404E9CD9E3ECB662395B4429C648139053FB521F828AF606B4D3DBAA14B5E77EFE75928FE1DC127A2FFA8DE3348B3C1856A429BF97E7E31C2E5BD66";
const char *y =
"011839296A789A3BC0045C8A5FB42C7D1BD998F54449579B446817AFBD17273E662C97EE72995EF42640C550B9013FAD0761353C7086A272C24088BE94769FD16650";
cry_mpi_load_str(&P.x, 16, x);
cry_mpi_load_str(&P.y, 16, y);
cry_mpi_set_int(&P.z, 1);
}
#endif
static void setup(void)
{
cry_mpi_init(&k);