Annotation of embedaddon/dnsmasq/src/crypto.c, revision 1.1

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

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