File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / dnsmasq / src / crypto.c
Revision 1.1.1.2 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Sep 27 11:02:07 2023 UTC (10 months, 2 weeks ago) by misho
Branches: dnsmasq, MAIN
CVS tags: v8_2p1, HEAD
Version 8.2p1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>