pike.git / src / post_modules / Nettle / hogweed.cmod

version» Context lines:

pike.git/src/post_modules/Nettle/hogweed.cmod:1: - /* -*- c -*- + /* -*- mode: c; encoding: utf-8; -*-   || This file is part of Pike. For copyright information see COPYRIGHT.   || Pike is distributed under GPL, LGPL and MPL. See the file COPYING   || for more information.   */    - #include "global.h" + #include "module.h"   #include "pike_compiler.h"   #include "builtin_functions.h"   #include "operators.h"   #include "interpret.h" - #include "module.h" - #include "mapping.h" - #include "stralloc.h" +    #include "constants.h"      #include "nettle_config.h"      #ifdef HAVE_LIBHOGWEED      DECLARATIONS      #include "nettle.h"   #include <nettle/dsa.h>
pike.git/src/post_modules/Nettle/hogweed.cmod:322:       f_aggregate(2);    }   }      /*! @endclass    */      #endif /* dsa_params_init */    - #ifdef HAVE_NETTLE_ECDSA_H + #if defined(HAVE_NETTLE_ECDSA_H) && (defined(HAVE_CURVE_NETTLE_SECP_192R1) || defined(HAVE_CURVE_NETTLE_SECP_224R1) || defined(HAVE_CURVE_NETTLE_SECP_256R1) || defined(HAVE_CURVE_NETTLE_SECP_384R1) || defined(HAVE_CURVE_NETTLE_SECP_521R1))   #include <nettle/ecc-curve.h>      #include <nettle/ecc.h>      #include <nettle/ecdsa.h>      #define SECP192R1 0   #define SECP224R1 1   #define SECP256R1 2   #define SECP384R1 3
pike.git/src/post_modules/Nettle/hogweed.cmod:381:    *! The curve type the object should be initialized as.    *! @int    *! @value Nettle.SECP192R1    *! @value Nettle.SECP224R1    *! @value Nettle.SECP256R1    *! @value Nettle.SECP384R1    *! @value Nettle.SECP521R1    *! @endint    */    PIKEFUN void create(int(0..) curve) -  flags ID_STATIC +  flags ID_PROTECTED;    {    mpz_t mpz_one;       if (THIS->curve) {    Pike_error("The curve has already been initialized!\n");    } -  +  pop_stack();       switch(curve) {   #ifdef HAVE_CURVE_NETTLE_SECP_192R1    case SECP192R1: THIS->curve = &nettle_secp_192r1; break;   #endif /* HAVE_CURVE_NETTLE_SECP_192R1 */   #ifdef HAVE_CURVE_NETTLE_SECP_224R1    case SECP224R1: THIS->curve = &nettle_secp_224r1; break;   #endif /* HAVE_CURVE_NETTLE_SECP_224R1 */   #ifdef HAVE_CURVE_NETTLE_SECP_256R1    case SECP256R1: THIS->curve = &nettle_secp_256r1; break;
pike.git/src/post_modules/Nettle/hogweed.cmod:412:   #ifdef HAVE_CURVE_NETTLE_SECP_521R1    case SECP521R1: THIS->curve = &nettle_secp_521r1; break;   #endif /* HAVE_CURVE_NETTLE_SECP_521R1 */    default:    Pike_error("Invalid curve\n");    break;    }       ecc_scalar_init(&THIS->scalar_one, THIS->curve);    mpz_init_set_si(mpz_one, 1); + #ifdef PIKE_DEBUG +  if( !ecc_scalar_set(&THIS->scalar_one, mpz_one) ) +  Pike_fatal("Unable to set scalar 1 on ECC curve.\n"); + #else    ecc_scalar_set(&THIS->scalar_one, mpz_one); -  + #endif    mpz_clear(mpz_one);    }       /*! @decl protected local int(0..1) `==(mixed x)    *!    *! @returns    *! Returns @expr{1@} if @[x] is the same @[Curve],    *! and @expr{0@} (zero) otherwise.    */    PIKEFUN int(0..1) `==(mixed x)
pike.git/src/post_modules/Nettle/hogweed.cmod:546:    /*! @decl int size()    *!    *! @returns    *! Returns the size in bits for a single coordinate on the curve.    */    PIKEFUN int size()    {   #ifdef HAVE_NETTLE_ECC_BIT_SIZE    push_int(ecc_bit_size(THIS->curve));   #else +  do { + #ifdef HAVE_CURVE_NETTLE_SECP_192R1    if (THIS->curve == &nettle_secp_192r1) {    push_int(192); -  } else if (THIS->curve == &nettle_secp_224r1) { +  break; +  } + #endif /* HAVE_CURVE_NETTLE_SECP_192R1 */ + #ifdef HAVE_CURVE_NETTLE_SECP_224R1 +  if (THIS->curve == &nettle_secp_224r1) {    push_int(224); -  } else if (THIS->curve == &nettle_secp_256r1) { +  break; +  } + #endif /* HAVE_CURVE_NETTLE_SECP_224R1 */ + #ifdef HAVE_CURVE_NETTLE_SECP_256R1 +  if (THIS->curve == &nettle_secp_256r1) {    push_int(256); -  } else if (THIS->curve == &nettle_secp_384r1) { +  break; +  } + #endif /* HAVE_CURVE_NETTLE_SECP_256R1 */ + #ifdef HAVE_CURVE_NETTLE_SECP_384R1 +  if (THIS->curve == &nettle_secp_384r1) {    push_int(384); -  } else if (THIS->curve == &nettle_secp_521r1) { +  break; +  } + #endif /* HAVE_CURVE_NETTLE_SECP_384R1 */ + #ifdef HAVE_CURVE_NETTLE_SECP_521R1 +  if (THIS->curve == &nettle_secp_521r1) {    push_int(521); -  } else { +  break; +  } + #endif /* HAVE_CURVE_NETTLE_SECP_521R1 */    push_int(0); -  +  } while(0); + #endif /* HAVE_NETTLE_ECC_BIT_SIZE */    } - #endif -  } +        /*! @decl Gmp.mpz new_scalar(function(int(0..):string(8bit)) rnd)    *!    *! @param rnd    *! Randomness function to use as source.    *!    *! @returns    *! Returns a random scalar suitable to use as an @[ECDSA] private key    *! or as an ECDH secret factor.    */
pike.git/src/post_modules/Nettle/hogweed.cmod:588:    ecc_scalar_init(&s, THIS->curve);       ecc_scalar_random(&s, rnd, random_func_wrapper);       push_object(ret = fast_clone_object(bignum_program));    ecc_scalar_get(&s, (mpz_ptr)ret->storage);       ecc_scalar_clear(&s);    }    -  static int Nettle_ECC_Curve_Point_program_fun_num; -  +     /*! @decl Point `*(Gmp.mpz|int scalar)    *!    *! Multiply the curve by a scalar.    *!    *! This can be used to get the public key from a private key.    *!    *! @returns    *! Returns a new @[Point] on the curve.    */    PIKEFUN Nettle_ECC_Curve_Point `*(object(Gmp.mpz)|int scalar)
pike.git/src/post_modules/Nettle/hogweed.cmod:707:    */    PIKECLASS Point    program_flags PROGRAM_USES_PARENT|PROGRAM_NEEDS_PARENT|PROGRAM_CLEAR_STORAGE;    {    CVAR struct ecc_point point;       /*! @decl inherit ECC_Curve::Point    */    EXTRA    { -  /* Perform an inherit of the Point class that our parent -  * contains via its inherit of __builtin.Nettle.ECC_Curve. +  /* Perform an inherit of the Point class (if any) that our parent +  * may contain via its inherit of __builtin.Nettle.ECC_Curve.    */ -  struct program *parent_prog = Pike_compiler->previous->new_program; -  struct object *parent_obj = Pike_compiler->previous->fake_object; -  int parent_Point_fun_num = -  really_low_find_shared_string_identifier(MK_STRING("Point"), -  parent_prog, -  SEE_PROTECTED|SEE_PRIVATE); -  if (parent_Point_fun_num >= 0) { -  struct program *parent_Point_prog = -  low_program_from_function(parent_obj, parent_Point_fun_num); -  if (parent_Point_prog) { -  parent_Point_fun_num = -  really_low_reference_inherited_identifier(Pike_compiler->previous, -  0, parent_Point_fun_num); -  low_inherit(parent_Point_prog, 0, -  parent_Point_fun_num, -  1 + 42, 0, NULL); +  lexical_inherit(1, MK_STRING("Point"), 0, REPORT_WARNING);    } -  } -  } +        INIT    {    const struct Nettle_ECC_Curve_struct *parent =    parent_storage(1, Nettle_ECC_Curve_program);    const struct ecc_curve *curve = parent->curve;       if (!curve) Pike_error("No curve selected.\n");    ecc_point_init(&THIS->point, curve);   
pike.git/src/post_modules/Nettle/hogweed.cmod:934:    program_flags PROGRAM_USES_PARENT|PROGRAM_NEEDS_PARENT|PROGRAM_CLEAR_STORAGE;    {    /*! @decl inherit Point    *!    *! This point represents the public key.    */    EXTRA    {    /* Perform an inherit of the Point class that our parent contains.    */ -  struct program *parent_prog = Pike_compiler->previous->new_program; -  struct object *parent_obj = Pike_compiler->previous->fake_object; -  int parent_Point_fun_num = -  really_low_find_shared_string_identifier(MK_STRING("Point"), -  parent_prog, -  SEE_PROTECTED|SEE_PRIVATE); -  if (parent_Point_fun_num >= 0) { -  struct program *parent_Point_prog = -  low_program_from_function(parent_obj, parent_Point_fun_num); -  - #ifdef PIKE_DEBUG -  if (parent_Point_prog != Nettle_ECC_Curve_Point_program) { -  Pike_fatal("Unexpected Point program.\n"); +  lexical_inherit(1, MK_STRING("Point"), 0, REPORT_ERROR);    } - #endif +     -  if (parent_Point_prog) { -  parent_Point_fun_num = -  really_low_reference_inherited_identifier(Pike_compiler->previous, -  0, parent_Point_fun_num); -  low_inherit(parent_Point_prog, 0, -  parent_Point_fun_num, -  1 + 42, 0, NULL); -  } -  } -  } -  +     /*! @decl inherit __builtin.Nettle.Sign    */    INHERIT "__builtin.Nettle.Sign";       CVAR struct ecc_scalar key;       PIKEVAR function(int(0..):string(0..255)) random    flags ID_PROTECTED;       INIT    { -  +  struct svalue *random;    const struct ecc_curve *curve =    (((const struct Nettle_ECC_Curve_struct *)parent_storage(1, Nettle_ECC_Curve_program))->curve);    if (!curve) Pike_error("No curve selected.\n");    ecc_scalar_init(&THIS->key, curve);    -  struct svalue *random = +  random =    simple_mapping_string_lookup(get_builtin_constants(), "random_string");    if(!random || (TYPEOF(*random) != T_FUNCTION))    Pike_error("Unable to resolve random function.\n");    assign_svalue(&THIS->random, random);    }       EXIT    {    const struct ecc_curve *curve =    (((const struct Nettle_ECC_Curve_struct *)parent_storage(1, Nettle_ECC_Curve_program))->curve);
pike.git/src/post_modules/Nettle/hogweed.cmod:1039:    */    PIKEFUN object(Gmp.mpz) get_private_key()    {    struct object *ret;    push_object(ret = fast_clone_object(bignum_program));    ecc_scalar_get(&THIS->key, (mpz_ptr)ret->storage);    }       /*! @decl void set_private_key(object(Gmp.mpz)|int k)    *! -  *! Set the private key (and corresponding private key). +  *! Set the private key (and corresponding public key).    *!    *! @note    *! Throws errors if the key isn't valid for the curve.    */    PIKEFUN void set_private_key(object(Gmp.mpz)|int k)    {    struct ecc_point *pub;    convert_svalue_to_bignum(k);    if (!ecc_scalar_set(&THIS->key, (mpz_srcptr)k->u.object->storage)) {    SIMPLE_ARG_ERROR("set_private_key", 1, "Invalid key for curve.");
pike.git/src/post_modules/Nettle/hogweed.cmod:1201:    }    /*! @endclass ECDSA    */   }      /*! @endclass ECC_Curve    */      #endif /* HAVE_NETTLE_ECDSA_H */    - #if defined(HAVE_NETTLE_EDDSA_H) && defined(HAVE_NETTLE_CURVE25519_H) + #if defined(HAVE_NETTLE_EDDSA_H) && defined(HAVE_NETTLE_CURVE25519_H) && defined(HAVE_NETTLE_ED25519_SHA512_SIGN)   #include <nettle/curve25519.h>      #include <nettle/eddsa.h>      /*! @class Curve25519    *!    *! Elliptic Curve Definition for the curve    *! @expr{y^2 = x^2 + 486662 x^2 + x (mod 2^255 - 19)@}.    *!    *! This curve is standardized in @rfc{7748@}.
pike.git/src/post_modules/Nettle/hogweed.cmod:1237:       /*! @decl string(7bit) name()    *!    *! Returns the name of the curve.    */    PIKEFUN string(7bit) name()    {    ref_push_string(MK_STRING("Curve25519"));    }    +  /*! @decl string(7bit) jose_name() +  *! +  *! Returns the name of the curve according to JOSE +  *! (@rfc{8037:3.1@}). +  *! +  *! @returns +  *! Returns the string @expr{"X25519"@}. +  *! +  *! @seealso +  *! @[name()] +  */ +  PIKEFUN string(7bit) jose_name() +  { +  ref_push_string(MK_STRING("X25519")); +  } +     /*! @decl int size()    *!    *! @returns    *! Returns the size in bits for a single coordinate on the curve.    */    PIKEFUN int size()    {    push_int(255);    }   
pike.git/src/post_modules/Nettle/hogweed.cmod:1322:    */    PIKECLASS Point    program_flags PROGRAM_USES_PARENT|PROGRAM_NEEDS_PARENT|PROGRAM_CLEAR_STORAGE;    {    PIKEVAR string(8bit) point flags ID_PRIVATE|ID_PROTECTED|ID_HIDDEN;       /*! @decl inherit ECC_Curve::Point    */    EXTRA    { -  /* Perform an inherit of the Point class that our parent -  * contains via its inherit of __builtin.Nettle.ECC_Curve. +  /* Perform an inherit of the Point class (if any) that our parent +  * may contain via its inherit of __builtin.Nettle.ECC_Curve.    */ -  struct program *parent_prog = Pike_compiler->previous->new_program; -  struct object *parent_obj = Pike_compiler->previous->fake_object; -  int parent_Point_fun_num = -  really_low_find_shared_string_identifier(MK_STRING("Point"), -  parent_prog, -  SEE_PROTECTED|SEE_PRIVATE); -  if (parent_Point_fun_num >= 0) { -  struct program *parent_Point_prog = -  low_program_from_function(parent_obj, parent_Point_fun_num); -  if (parent_Point_prog) { -  parent_Point_fun_num = -  really_low_reference_inherited_identifier(Pike_compiler->previous, -  0, parent_Point_fun_num); -  low_inherit(parent_Point_prog, 0, -  parent_Point_fun_num, -  1 + 42, 0, NULL); +  lexical_inherit(1, MK_STRING("Point"), 0, REPORT_WARNING);    } -  } -  } +        PIKEFUN void set(string(8bit) x, string(8bit)|void y)    flags ID_VARIANT;    {    if (x->len != CURVE25519_SIZE) {    Pike_error("Invalid x.\n");    }    if (y && y->len) {    Pike_error("Invalid y.\n");    }
pike.git/src/post_modules/Nettle/hogweed.cmod:1419:    /*! @endclass Point    */       /*! @class EdDSA    *!    *! Edwards Curve Digital Signing Algorithm    */    PIKECLASS EdDSA    program_flags PROGRAM_USES_PARENT|PROGRAM_NEEDS_PARENT|PROGRAM_CLEAR_STORAGE;    { +  /*! @decl inherit Point +  *! +  *! This point represents the public key. +  */ +  EXTRA +  { +  /* Perform an inherit of the Point class that our parent contains. +  */ +  lexical_inherit(1, MK_STRING("Point"), 0, REPORT_ERROR); +  } +     /*! @decl inherit __builtin.Nettle.Sign    */    INHERIT "__builtin.Nettle.Sign";       PIKEVAR string(8bit) private_key flags ID_PRIVATE|ID_HIDDEN;    -  PIKEVAR string(8bit) public_key flags ID_PRIVATE|ID_HIDDEN; -  +     PIKEVAR function(int(0..):string(0..255)) random    flags ID_PROTECTED;       INIT    {    struct svalue *random =    simple_mapping_string_lookup(get_builtin_constants(), "random_string");    if(!random || (TYPEOF(*random) != T_FUNCTION))    Pike_error("Unable to resolve random function.\n");    assign_svalue(&THIS->random, random);
pike.git/src/post_modules/Nettle/hogweed.cmod:1448:       /*! @decl string(7bit) name()    *!    *! Returns the string @expr{"EdDSA"@}.    */    PIKEFUN string(7bit) name()    {    ref_push_string(MK_STRING("EdDSA"));    }    +  /*! @decl string(7bit) jose_name() +  *! +  *! Returns the string @expr{"Ed25519"@}. +  */ +  PIKEFUN string(7bit) jose_name() +  { +  ref_push_string(MK_STRING("Ed25519")); +  } +     /*! @decl Curve25519 get_curve()    *!    *! Get the elliptic curve that is in use.    */    PIKEFUN object(Nettle_Curve25519) get_curve()    {    struct external_variable_context loc;    loc.o = Pike_fp->current_object;    loc.inherit = Pike_fp->context;    find_external_context(&loc, 1);
pike.git/src/post_modules/Nettle/hogweed.cmod:1484:    /*! @decl void set_private_key(string(8bit) k)    *!    *! Set the private key (and corresponding public key).    *!    *! @note    *! Throws errors if the key isn't valid for the curve.    */    PIKEFUN void set_private_key(string(8bit) k)    {    struct pike_string *pub; +  struct Nettle_Curve25519_Point_struct *point;       if (k->len != ED25519_KEY_SIZE) Pike_error("Invalid private key.\n");       if (THIS->private_key) {    free_string(THIS->private_key);    }    copy_shared_string(THIS->private_key, k);       /* Set the corresponding public key, */    pub = begin_shared_string(ED25519_KEY_SIZE);       ed25519_sha512_public_key(STR0(pub), STR0(k));    -  if (THIS->public_key) { -  free_string(THIS->public_key); +  point = get_inherited_storage(1, Nettle_Curve25519_Point_program); +  if (point->point) { +  free_string(point->point);    } -  THIS->public_key = end_shared_string(pub); +  point->point = end_shared_string(pub);    }       /*! @decl string(8bit) get_x()    *!    *! Get the x coordinate of the public key.    */    PIKEFUN string(8bit) get_x()    { -  if (THIS->public_key) { -  ref_push_string(THIS->public_key); +  struct Nettle_Curve25519_Point_struct *point; +  point = get_inherited_storage(1, Nettle_Curve25519_Point_program); +  if (point->point) { +  ref_push_string(point->point);    } else {    push_undefined();    }    }       /*! @decl void set_public_key(string(8bit) x)    *!    *! Change to the selected point on the curve as public key.    *!    *! @note    *! Throws errors if the point isn't on the curve.    */    PIKEFUN void set_public_key(string(8bit) x)    { -  if (THIS->public_key == x) return; +  struct Nettle_Curve25519_Point_struct *point; +  point = get_inherited_storage(1, Nettle_Curve25519_Point_program); +  if (point->point == x) return;    if (x->len != ED25519_KEY_SIZE) Pike_error("Invalid key.\n"); -  if (THIS->public_key) { -  free_string(THIS->public_key); +  if (point->point) { +  free_string(point->point);    }    if (THIS->private_key) {    free_string(THIS->private_key);    THIS->private_key = NULL;    } -  copy_shared_string(THIS->public_key, x); +  copy_shared_string(point->point, x);    }       /*! @decl void set_random(function(int(0..):string(8bit)) r)    *!    *! Set the random function, used to generate keys and parameters,    *! to the function @[r].    */    PIKEFUN void set_random(function(int(0..):string(8bit)) r)    {    assign_svalue(&THIS->random, r);    }       /*! @decl int(0..1) raw_verify(string(8bit) message, string(8bit) signature)    *!    *! Verify the @[signature] against the @[message].    */    PIKEFUN int(0..1) raw_verify(string(8bit) message, string(8bit) signature)    { -  if (!THIS->public_key) Pike_error("No public key.\n"); +  struct Nettle_Curve25519_Point_struct *point; +  point = get_inherited_storage(1, Nettle_Curve25519_Point_program); +  if (!point->point) Pike_error("No public key.\n");       if (signature->len != ED25519_SIGNATURE_SIZE) {    push_int(0);    return;    }    -  push_int(ed25519_sha512_verify(STR0(THIS->public_key), +  push_int(ed25519_sha512_verify(STR0(point->point),    message->len, STR0(message),    STR0(signature)));    }       /*! @decl string(8bit) raw_sign(string(8bit) message)    *!    *! Sign the @[message].    */    PIKEFUN string(8bit) raw_sign(string(8bit) message)    {    struct pike_string *res; -  +  struct Nettle_Curve25519_Point_struct *point; +  point = get_inherited_storage(1, Nettle_Curve25519_Point_program);       if (!THIS->private_key) Pike_error("No private key.\n"); -  if (!THIS->public_key) Pike_error("No public key.\n"); +  if (!point->point) Pike_error("No public key.\n");       res = begin_shared_string(ED25519_SIGNATURE_SIZE);    -  ed25519_sha512_sign(STR0(THIS->public_key), STR0(THIS->private_key), +  ed25519_sha512_sign(STR0(point->point), STR0(THIS->private_key),    message->len, STR0(message),    STR0(res));       push_string(end_shared_string(res));    }       /*! @decl void generate_key()    *!    *! Generate a new set of private and public keys on the current curve.    */
pike.git/src/post_modules/Nettle/hogweed.cmod:1602:    apply_svalue(&THIS->random, 1);    apply_current(f_Nettle_Curve25519_EdDSA_set_private_key_fun_num, 1);    }    }    /*! @endclass EdDSA    */   }      /*! @endclass Curve25519    */ - #endif /* HAVE_NETTLE_EDDSA_H && HAVE_NETTLE_CURVE25519_H */ + #endif /* HAVE_NETTLE_EDDSA_H && HAVE_NETTLE_CURVE25519_H && HAVE_NETTLE_ED25519_SHA512_SIGN */      /*! @endmodule Nettle    */      void   hogweed_init(void)   {    INIT;      #ifdef HAVE_NETTLE_ECDSA_H
pike.git/src/post_modules/Nettle/hogweed.cmod:1630:    ADD_INT_CONSTANT("SECP256R1", SECP256R1, 0);   #endif /* HAVE_CURVE_NETTLE_SECP_256R1 */   #ifdef HAVE_CURVE_NETTLE_SECP_384R1    ADD_INT_CONSTANT("SECP384R1", SECP384R1, 0);   #endif /* HAVE_CURVE_NETTLE_SECP_384R1 */   #ifdef HAVE_CURVE_NETTLE_SECP_521R1    ADD_INT_CONSTANT("SECP521R1", SECP521R1, 0);   #endif /* HAVE_CURVE_NETTLE_SECP_521R1 */   #endif /* HAVE_NETTLE_ECDSA_H */    + #if defined(HAVE_NETTLE_EDDSA_H) && defined(HAVE_NETTLE_CURVE25519_H) && defined(HAVE_NETTLE_ED25519_SHA512_SIGN)   #ifdef NETTLE_CURVE25519_RFC7748    ADD_INT_CONSTANT("CURVE25519_RFC7748", 1, 0);   #endif -  + #endif   }      void   hogweed_exit(void)   {    EXIT;   }      #endif