Skip to content

Commit 1e93393

Browse files
committed
FEAT: new native ecdh for Elliptic-curve Diffie-Hellman key exchange.
Using Kenneth MacKay's [micro-ecc project](https://github.com/kmackay/micro-ecc) For usage example see the modified `dh-test.r3` file.
1 parent 5e06fd8 commit 1e93393

9 files changed

+3880
-0
lines changed

NOTICE

+4
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,10 @@ Credits for Non-REBOL orginated C files and modules
1111
Unicode encoding/decoding functions:
1212
Copyright 2001-2004 Unicode, Inc.
1313

14+
ECDH:
15+
Copyright (c) 2014, Kenneth MacKay - https://github.com/kmackay/micro-ecc
16+
All rights reserved.
17+
1418
MD5:
1519
This software contains code derived from the RSA Data Security
1620
Inc. MD5 Message-Digest Algorithm, including various

src/core/n-crypt.c

+159
Original file line numberDiff line numberDiff line change
@@ -508,3 +508,162 @@
508508
return R_RET;
509509

510510
}
511+
512+
513+
#include "uECC.h"
514+
const struct uECC_Curve_t* ECC_curves[5] = {0,0,0,0,0};
515+
typedef struct {
516+
REBCNT curve_type;
517+
uint8_t public[64];
518+
uint8_t private[32];
519+
} ECC_CTX;
520+
521+
/***********************************************************************
522+
**
523+
*/ REBNATIVE(ecdh)
524+
/*
525+
// ecdh: native [
526+
// "Elliptic-curve Diffie-Hellman key exchange"
527+
// key [handle! none!] "Keypair to work with, may be NONE for /init refinement"
528+
// /init "Initialize ECC keypair."
529+
// type [word!] "One of supported curves: [secp256k1 secp256r1 secp224r1 secp192r1 secp160r1]"
530+
// /curve "Returns handles curve type"
531+
// /public "Returns public key as a binary"
532+
// /secret "Computes secret result using peer's public key"
533+
// public-key [binary!] "Peer's public key"
534+
// /release "Releases internal ECDH key resources"
535+
// ]
536+
***********************************************************************/
537+
{
538+
REBVAL *val_handle = D_ARG(1);
539+
REBOOL ref_init = D_REF(2);
540+
REBVAL *val_curve = D_ARG(3);
541+
REBOOL ref_type = D_REF(4);
542+
REBOOL ref_public = D_REF(5);
543+
REBOOL ref_secret = D_REF(6);
544+
REBVAL *val_public = D_ARG(7);
545+
REBOOL ref_release = D_REF(8);
546+
547+
REBSER *ecc_ser = NULL;
548+
REBSER *bin = NULL;
549+
REBVAL *ret;
550+
REBCNT curve_type = 0;
551+
uECC_Curve curve = NULL;
552+
ECC_CTX *ecc = NULL;
553+
554+
if (IS_HANDLE(val_handle)) {
555+
if (VAL_HANDLE_TYPE(val_handle) != SYM_ECDH || VAL_HANDLE_DATA(val_handle) == NULL) {
556+
Trap0(RE_INVALID_HANDLE);
557+
}
558+
ecc_ser = VAL_HANDLE_DATA(val_handle);
559+
ecc = (ECC_CTX*)SERIES_DATA(ecc_ser);
560+
curve_type = ecc->curve_type;
561+
}
562+
563+
if (ref_init) {
564+
if(ecc_ser == NULL) {
565+
ecc_ser = Make_Series(sizeof(ECC_CTX), 1, FALSE);
566+
}
567+
ecc = (ECC_CTX*)SERIES_DATA(ecc_ser);
568+
CLEARS(ecc);
569+
curve_type = ecc->curve_type = VAL_WORD_CANON(val_curve);
570+
SET_HANDLE(val_handle, ecc_ser, SYM_ECDH, HANDLE_SERIES);
571+
}
572+
573+
switch (curve_type) {
574+
case SYM_SECP256K1:
575+
curve = ECC_curves[4];
576+
if(curve == NULL) {
577+
curve = uECC_secp256k1();
578+
ECC_curves[4] = curve;
579+
}
580+
break;
581+
case SYM_SECP256R1:
582+
curve = ECC_curves[3];
583+
if(curve == NULL) {
584+
curve = uECC_secp256r1();
585+
ECC_curves[3] = curve;
586+
}
587+
break;
588+
case SYM_SECP224R1:
589+
curve = ECC_curves[2];
590+
if(curve == NULL) {
591+
curve = uECC_secp224r1();
592+
ECC_curves[2] = curve;
593+
}
594+
break;
595+
case SYM_SECP192R1:
596+
curve = ECC_curves[1];
597+
if(curve == NULL) {
598+
curve = uECC_secp192r1();
599+
ECC_curves[1] = curve;
600+
}
601+
break;
602+
case SYM_SECP160R1:
603+
curve = ECC_curves[0];
604+
if(curve == NULL) {
605+
curve = uECC_secp160r1();
606+
ECC_curves[0] = curve;
607+
}
608+
break;
609+
default:
610+
return R_NONE;
611+
}
612+
613+
if (ref_init) {
614+
if(!uECC_make_key(ecc->public, ecc->private, curve)) {
615+
puts("failed to init ECDH key");
616+
Trap0(RE_INVALID_HANDLE); //TODO: change to something better!
617+
} else return R_ARG1;
618+
}
619+
620+
if (ref_secret) {
621+
if (IS_HANDLE(val_handle)) {
622+
bin = Make_Binary(32);
623+
if (!uECC_shared_secret(VAL_DATA(val_public), ecc->private, BIN_DATA(bin), curve)) {
624+
return R_NONE;
625+
}
626+
if(ref_release) {
627+
CLEARS(ecc);
628+
HANDLE_SET_FLAG(val_handle, HANDLE_RELEASABLE);
629+
}
630+
SET_BINARY(D_RET, bin);
631+
BIN_LEN(bin) = 32;
632+
return R_RET;
633+
}
634+
else {
635+
Trap0(RE_INVALID_HANDLE);
636+
return R_NONE;
637+
}
638+
}
639+
640+
if (ref_public) {
641+
if (IS_HANDLE(val_handle)) {
642+
bin = Make_Binary(64);
643+
COPY_MEM(BIN_DATA(bin), ecc->public, 64);
644+
SET_BINARY(D_RET, bin);
645+
BIN_LEN(bin) = 64;
646+
return R_RET;
647+
}
648+
else {
649+
return R_NONE;
650+
}
651+
}
652+
653+
if(ref_release) {
654+
CLEARS(ecc);
655+
HANDLE_SET_FLAG(val_handle, HANDLE_RELEASABLE);
656+
return R_ARG1;
657+
}
658+
659+
if (ref_type) {
660+
if (IS_HANDLE(val_handle)) {
661+
Init_Word(val_curve, curve_type);
662+
return R_ARG3;
663+
}
664+
else {
665+
return R_NONE;
666+
}
667+
}
668+
return R_ARG1;
669+
}

0 commit comments

Comments
 (0)