"Fossies" - the Fresh Open Source Software Archive

Member "dnsmasq-2.85/src/crypto.c" (7 Apr 2021, 12613 Bytes) of package /linux/misc/dns/dnsmasq-2.85.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "crypto.c" see the Fossies "Dox" file reference documentation and the latest Fossies "Diffs" side-by-side code changes report: 2.84_vs_2.85.

    1 /* dnsmasq is Copyright (c) 2000-2021 Simon Kelley
    2 
    3    This program is free software; you can redistribute it and/or modify
    4    it under the terms of the GNU General Public License as published by
    5    the Free Software Foundation; version 2 dated June, 1991, or
    6    (at your option) version 3 dated 29 June, 2007.
    7  
    8    This program is distributed in the hope that it will be useful,
    9    but WITHOUT ANY WARRANTY; without even the implied warranty of
   10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   11    GNU General Public License for more details.
   12      
   13    You should have received a copy of the GNU General Public License
   14    along with this program.  If not, see <http://www.gnu.org/licenses/>.
   15 */
   16 
   17 #include "dnsmasq.h"
   18 
   19 #ifdef HAVE_DNSSEC
   20 
   21 /* Minimal version of nettle */
   22 #define MIN_VERSION(major, minor) (NETTLE_VERSION_MAJOR == (major) && NETTLE_VERSION_MINOR >= (minor)) || \
   23                   (NETTLE_VERSION_MAJOR > (major))
   24 
   25 #include <nettle/rsa.h>
   26 #include <nettle/ecdsa.h>
   27 #include <nettle/ecc-curve.h>
   28 #if !defined(NETTLE_VERSION_MAJOR)
   29 #define NETTLE_VERSION_MAJOR 2
   30 #endif
   31 #if MIN_VERSION(3, 1)
   32 #include <nettle/eddsa.h>
   33 #endif
   34 #if MIN_VERSION(3, 6)
   35 #  include <nettle/gostdsa.h>
   36 #endif
   37 #endif
   38 
   39 #if defined(HAVE_DNSSEC) || defined(HAVE_CRYPTOHASH)
   40 #include <nettle/nettle-meta.h>
   41 #include <nettle/bignum.h>
   42 
   43 /* Implement a "hash-function" to the nettle API, which simply returns
   44    the input data, concatenated into a single, statically maintained, buffer.
   45 
   46    Used for the EdDSA sigs, which operate on the whole message, rather 
   47    than a digest. */
   48 
   49 struct null_hash_digest
   50 {
   51   uint8_t *buff;
   52   size_t len;
   53 };
   54 
   55 struct null_hash_ctx
   56 {
   57   size_t len;
   58 };
   59 
   60 static size_t null_hash_buff_sz = 0;
   61 static uint8_t *null_hash_buff = NULL;
   62 #define BUFF_INCR 128
   63 
   64 static void null_hash_init(void *ctx)
   65 {
   66   ((struct null_hash_ctx *)ctx)->len = 0;
   67 }
   68 
   69 static void null_hash_update(void *ctxv, size_t length, const uint8_t *src)
   70 {
   71   struct null_hash_ctx *ctx = ctxv;
   72   size_t new_len = ctx->len + length;
   73   
   74   if (new_len > null_hash_buff_sz)
   75     {
   76       uint8_t *new;
   77       
   78       if (!(new = whine_malloc(new_len + BUFF_INCR)))
   79     return;
   80 
   81       if (null_hash_buff)
   82     {
   83       if (ctx->len != 0)
   84         memcpy(new, null_hash_buff, ctx->len);
   85       free(null_hash_buff);
   86     }
   87       
   88       null_hash_buff_sz = new_len + BUFF_INCR;
   89       null_hash_buff = new;
   90     }
   91 
   92   memcpy(null_hash_buff + ctx->len, src, length);
   93   ctx->len += length;
   94 }
   95  
   96 
   97 static void null_hash_digest(void *ctx, size_t length, uint8_t *dst)
   98 {
   99   (void)length;
  100   
  101   ((struct null_hash_digest *)dst)->buff = null_hash_buff;
  102   ((struct null_hash_digest *)dst)->len = ((struct null_hash_ctx *)ctx)->len;
  103 }
  104 
  105 static struct nettle_hash null_hash = {
  106   "null_hash",
  107   sizeof(struct null_hash_ctx),
  108   sizeof(struct null_hash_digest),
  109   0,
  110   (nettle_hash_init_func *) null_hash_init,
  111   (nettle_hash_update_func *) null_hash_update,
  112   (nettle_hash_digest_func *) null_hash_digest
  113 };
  114 
  115 /* Find pointer to correct hash function in nettle library */
  116 const struct nettle_hash *hash_find(char *name)
  117 {
  118   if (!name)
  119     return NULL;
  120   
  121   /* We provide a "null" hash which returns the input data as digest. */
  122   if (strcmp(null_hash.name, name) == 0)
  123     return &null_hash;
  124 
  125   /* libnettle >= 3.4 provides nettle_lookup_hash() which avoids nasty ABI
  126      incompatibilities if sizeof(nettle_hashes) changes between library
  127      versions. */
  128 #if MIN_VERSION(3, 4)
  129   return nettle_lookup_hash(name);
  130 #else
  131   {
  132     int i;
  133 
  134     for (i = 0; nettle_hashes[i]; i++)
  135       if (strcmp(nettle_hashes[i]->name, name) == 0)
  136     return nettle_hashes[i];
  137   }
  138   
  139   return NULL;
  140 #endif
  141 }
  142 
  143 /* expand ctx and digest memory allocations if necessary and init hash function */
  144 int hash_init(const struct nettle_hash *hash, void **ctxp, unsigned char **digestp)
  145 {
  146   static void *ctx = NULL;
  147   static unsigned char *digest = NULL;
  148   static unsigned int ctx_sz = 0;
  149   static unsigned int digest_sz = 0;
  150 
  151   void *new;
  152 
  153   if (ctx_sz < hash->context_size)
  154     {
  155       if (!(new = whine_malloc(hash->context_size)))
  156     return 0;
  157       if (ctx)
  158     free(ctx);
  159       ctx = new;
  160       ctx_sz = hash->context_size;
  161     }
  162   
  163   if (digest_sz < hash->digest_size)
  164     {
  165       if (!(new = whine_malloc(hash->digest_size)))
  166     return 0;
  167       if (digest)
  168     free(digest);
  169       digest = new;
  170       digest_sz = hash->digest_size;
  171     }
  172 
  173   *ctxp = ctx;
  174   *digestp = digest;
  175 
  176   hash->init(ctx);
  177 
  178   return 1;
  179 }
  180 
  181 #endif /* defined(HAVE_DNSSEC) || defined(HAVE_CRYPTOHASH) */
  182 
  183 #ifdef HAVE_DNSSEC
  184   
  185 static int dnsmasq_rsa_verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
  186                   unsigned char *digest, size_t digest_len, int algo)
  187 {
  188   unsigned char *p;
  189   size_t exp_len;
  190   
  191   static struct rsa_public_key *key = NULL;
  192   static mpz_t sig_mpz;
  193 
  194   (void)digest_len;
  195   
  196   if (key == NULL)
  197     {
  198       if (!(key = whine_malloc(sizeof(struct rsa_public_key))))
  199     return 0;
  200       
  201       nettle_rsa_public_key_init(key);
  202       mpz_init(sig_mpz);
  203     }
  204   
  205   if ((key_len < 3) || !(p = blockdata_retrieve(key_data, key_len, NULL)))
  206     return 0;
  207   
  208   key_len--;
  209   if ((exp_len = *p++) == 0)
  210     {
  211       GETSHORT(exp_len, p);
  212       key_len -= 2;
  213     }
  214   
  215   if (exp_len >= key_len)
  216     return 0;
  217   
  218   key->size =  key_len - exp_len;
  219   mpz_import(key->e, exp_len, 1, 1, 0, 0, p);
  220   mpz_import(key->n, key->size, 1, 1, 0, 0, p + exp_len);
  221 
  222   mpz_import(sig_mpz, sig_len, 1, 1, 0, 0, sig);
  223   
  224   switch (algo)
  225     {
  226     case 5: case 7:
  227       return nettle_rsa_sha1_verify_digest(key, digest, sig_mpz);
  228     case 8:
  229       return nettle_rsa_sha256_verify_digest(key, digest, sig_mpz);
  230     case 10:
  231       return nettle_rsa_sha512_verify_digest(key, digest, sig_mpz);
  232     }
  233 
  234   return 0;
  235 }  
  236 
  237 static int dnsmasq_ecdsa_verify(struct blockdata *key_data, unsigned int key_len, 
  238                 unsigned char *sig, size_t sig_len,
  239                 unsigned char *digest, size_t digest_len, int algo)
  240 {
  241   unsigned char *p;
  242   unsigned int t;
  243   struct ecc_point *key;
  244 
  245   static struct ecc_point *key_256 = NULL, *key_384 = NULL;
  246   static mpz_t x, y;
  247   static struct dsa_signature *sig_struct;
  248 #if !MIN_VERSION(3, 4)
  249 #define nettle_get_secp_256r1() (&nettle_secp_256r1)
  250 #define nettle_get_secp_384r1() (&nettle_secp_384r1)
  251 #endif
  252   
  253   if (!sig_struct)
  254     {
  255       if (!(sig_struct = whine_malloc(sizeof(struct dsa_signature))))
  256     return 0;
  257       
  258       nettle_dsa_signature_init(sig_struct);
  259       mpz_init(x);
  260       mpz_init(y);
  261     }
  262   
  263   switch (algo)
  264     {
  265     case 13:
  266       if (!key_256)
  267     {
  268       if (!(key_256 = whine_malloc(sizeof(struct ecc_point))))
  269         return 0;
  270       
  271       nettle_ecc_point_init(key_256, nettle_get_secp_256r1());
  272     }
  273       
  274       key = key_256;
  275       t = 32;
  276       break;
  277       
  278     case 14:
  279       if (!key_384)
  280     {
  281       if (!(key_384 = whine_malloc(sizeof(struct ecc_point))))
  282         return 0;
  283       
  284       nettle_ecc_point_init(key_384, nettle_get_secp_384r1());
  285     }
  286       
  287       key = key_384;
  288       t = 48;
  289       break;
  290         
  291     default:
  292       return 0;
  293     }
  294   
  295   if (sig_len != 2*t || key_len != 2*t ||
  296       !(p = blockdata_retrieve(key_data, key_len, NULL)))
  297     return 0;
  298   
  299   mpz_import(x, t , 1, 1, 0, 0, p);
  300   mpz_import(y, t , 1, 1, 0, 0, p + t);
  301 
  302   if (!ecc_point_set(key, x, y))
  303     return 0;
  304   
  305   mpz_import(sig_struct->r, t, 1, 1, 0, 0, sig);
  306   mpz_import(sig_struct->s, t, 1, 1, 0, 0, sig + t);
  307   
  308   return nettle_ecdsa_verify(key, digest_len, digest, sig_struct);
  309 }
  310 
  311 #if MIN_VERSION(3, 6)
  312 static int dnsmasq_gostdsa_verify(struct blockdata *key_data, unsigned int key_len, 
  313                   unsigned char *sig, size_t sig_len,
  314                   unsigned char *digest, size_t digest_len, int algo)
  315 {
  316   unsigned char *p;
  317   
  318   static struct ecc_point *gost_key = NULL;
  319   static mpz_t x, y;
  320   static struct dsa_signature *sig_struct;
  321 
  322   if (algo != 12 ||
  323       sig_len != 64 || key_len != 64 ||
  324       !(p = blockdata_retrieve(key_data, key_len, NULL)))
  325     return 0;
  326   
  327   if (!sig_struct)
  328     {
  329       if (!(sig_struct = whine_malloc(sizeof(struct dsa_signature))) ||
  330       !(gost_key = whine_malloc(sizeof(struct ecc_point))))
  331     return 0;
  332       
  333       nettle_dsa_signature_init(sig_struct);
  334       nettle_ecc_point_init(gost_key, nettle_get_gost_gc256b());
  335       mpz_init(x);
  336       mpz_init(y);
  337     }
  338     
  339   mpz_import(x, 32 , 1, 1, 0, 0, p);
  340   mpz_import(y, 32 , 1, 1, 0, 0, p + 32);
  341 
  342   if (!ecc_point_set(gost_key, x, y))
  343     return 0;
  344   
  345   mpz_import(sig_struct->r, 32, 1, 1, 0, 0, sig);
  346   mpz_import(sig_struct->s, 32, 1, 1, 0, 0, sig + 32);
  347   
  348   return nettle_gostdsa_verify(gost_key, digest_len, digest, sig_struct);
  349 }
  350 #endif
  351 
  352 #if MIN_VERSION(3, 1)
  353 static int dnsmasq_eddsa_verify(struct blockdata *key_data, unsigned int key_len, 
  354                 unsigned char *sig, size_t sig_len,
  355                 unsigned char *digest, size_t digest_len, int algo)
  356 {
  357   unsigned char *p;
  358    
  359   if (digest_len != sizeof(struct null_hash_digest) ||
  360       !(p = blockdata_retrieve(key_data, key_len, NULL)))
  361     return 0;
  362   
  363   /* The "digest" returned by the null_hash function is simply a struct null_hash_digest
  364      which has a pointer to the actual data and a length, because the buffer
  365      may need to be extended during "hashing". */
  366   
  367   switch (algo)
  368     {
  369     case 15:
  370       if (key_len != ED25519_KEY_SIZE ||
  371       sig_len != ED25519_SIGNATURE_SIZE)
  372     return 0;
  373 
  374       return ed25519_sha512_verify(p,
  375                    ((struct null_hash_digest *)digest)->len,
  376                    ((struct null_hash_digest *)digest)->buff,
  377                    sig);
  378       
  379 #if MIN_VERSION(3, 6)
  380     case 16:
  381       if (key_len != ED448_KEY_SIZE ||
  382       sig_len != ED448_SIGNATURE_SIZE)
  383     return 0;
  384 
  385       return ed448_shake256_verify(p,
  386                    ((struct null_hash_digest *)digest)->len,
  387                    ((struct null_hash_digest *)digest)->buff,
  388                    sig);
  389 #endif
  390 
  391     }
  392 
  393   return 0;
  394 }
  395 #endif
  396 
  397 static int (*verify_func(int algo))(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
  398                  unsigned char *digest, size_t digest_len, int algo)
  399 {
  400     
  401   /* Ensure at runtime that we have support for this digest */
  402   if (!hash_find(algo_digest_name(algo)))
  403     return NULL;
  404   
  405   /* This switch defines which sig algorithms we support, can't introspect Nettle for that. */
  406   switch (algo)
  407     {
  408     case 5: case 7: case 8: case 10:
  409       return dnsmasq_rsa_verify;
  410 
  411 #if MIN_VERSION(3, 6)
  412     case 12:
  413       return dnsmasq_gostdsa_verify;
  414 #endif
  415       
  416     case 13: case 14:
  417       return dnsmasq_ecdsa_verify;
  418 #if MIN_VERSION(3, 1)
  419     case 15: case 16:
  420       return dnsmasq_eddsa_verify;
  421 #endif
  422     }
  423   
  424   return NULL;
  425 }
  426 
  427 int verify(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
  428        unsigned char *digest, size_t digest_len, int algo)
  429 {
  430 
  431   int (*func)(struct blockdata *key_data, unsigned int key_len, unsigned char *sig, size_t sig_len,
  432           unsigned char *digest, size_t digest_len, int algo);
  433   
  434   func = verify_func(algo);
  435   
  436   if (!func)
  437     return 0;
  438 
  439   return (*func)(key_data, key_len, sig, sig_len, digest, digest_len, algo);
  440 }
  441 
  442 /* Note the ds_digest_name(), algo_digest_name() and nsec3_digest_name()
  443    define which algo numbers we support. If algo_digest_name() returns
  444    non-NULL for an algorithm number, we assume that algorithm is 
  445    supported by verify(). */
  446 
  447 /* http://www.iana.org/assignments/ds-rr-types/ds-rr-types.xhtml */
  448 char *ds_digest_name(int digest)
  449 {
  450   switch (digest)
  451     {
  452     case 1: return "sha1";
  453     case 2: return "sha256";
  454     case 3: return "gosthash94";
  455     case 4: return "sha384";
  456     default: return NULL;
  457     }
  458 }
  459  
  460 /* http://www.iana.org/assignments/dns-sec-alg-numbers/dns-sec-alg-numbers.xhtml */
  461 char *algo_digest_name(int algo)
  462 {
  463   switch (algo)
  464     {
  465     case 1: return NULL;          /* RSA/MD5 - Must Not Implement.  RFC 6944 para 2.3. */
  466     case 2: return NULL;          /* Diffie-Hellman */
  467     case 3: return NULL; ;        /* DSA/SHA1 - Must Not Implement. RFC 8624 section 3.1 */ 
  468     case 5: return "sha1";        /* RSA/SHA1 */
  469     case 6: return NULL;          /* DSA-NSEC3-SHA1 - Must Not Implement. RFC 8624 section 3.1 */
  470     case 7: return "sha1";        /* RSASHA1-NSEC3-SHA1 */
  471     case 8: return "sha256";      /* RSA/SHA-256 */
  472     case 10: return "sha512";     /* RSA/SHA-512 */
  473     case 12: return "gosthash94"; /* ECC-GOST */
  474     case 13: return "sha256";     /* ECDSAP256SHA256 */
  475     case 14: return "sha384";     /* ECDSAP384SHA384 */     
  476     case 15: return "null_hash";  /* ED25519 */
  477     case 16: return "null_hash";  /* ED448 */
  478     default: return NULL;
  479     }
  480 }
  481   
  482 /* http://www.iana.org/assignments/dnssec-nsec3-parameters/dnssec-nsec3-parameters.xhtml */
  483 char *nsec3_digest_name(int digest)
  484 {
  485   switch (digest)
  486     {
  487     case 1: return "sha1";
  488     default: return NULL;
  489     }
  490 }
  491 
  492 #endif