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

1.1.1.2 ! misho       1: /* dnsmasq is Copyright (c) 2000-2022 Simon Kelley
1.1       misho       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: 
1.1.1.2 ! misho      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)))
1.1       misho      32: 
1.1.1.2 ! misho      33: #endif /* defined(HAVE_DNSSEC) || defined(HAVE_CRYPTOHASH) */
        !            34: 
        !            35: #if defined(HAVE_DNSSEC)
1.1       misho      36: #include <nettle/rsa.h>
                     37: #include <nettle/ecdsa.h>
                     38: #include <nettle/ecc-curve.h>
1.1.1.2 ! misho      39: #if MIN_VERSION(3, 1)
1.1       misho      40: #include <nettle/eddsa.h>
                     41: #endif
1.1.1.2 ! misho      42: #if MIN_VERSION(3, 6)
        !            43: #  include <nettle/gostdsa.h>
1.1       misho      44: #endif
                     45: 
1.1.1.2 ! misho      46: #if MIN_VERSION(3, 1)
1.1       misho      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: 
1.1.1.2 ! misho     118: #endif /* MIN_VERSION(3, 1) */
1.1       misho     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;
1.1.1.2 ! misho     221: #if !MIN_VERSION(3, 4)
1.1       misho     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: 
1.1.1.2 ! misho     284: #if MIN_VERSION(3, 6)
1.1       misho     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:     
1.1.1.2 ! misho     312:   mpz_import(x, 32, -1, 1, 0, 0, p);
        !           313:   mpz_import(y, 32, -1, 1, 0, 0, p + 32);
1.1       misho     314: 
                    315:   if (!ecc_point_set(gost_key, x, y))
1.1.1.2 ! misho     316:     return 0; 
1.1       misho     317:   
1.1.1.2 ! misho     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);
1.1       misho     320:   
                    321:   return nettle_gostdsa_verify(gost_key, digest_len, digest, sig_struct);
                    322: }
                    323: #endif
                    324: 
1.1.1.2 ! misho     325: #if MIN_VERSION(3, 1)
1.1       misho     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:       
1.1.1.2 ! misho     352: #if MIN_VERSION(3, 6)
1.1       misho     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: }
1.1.1.2 ! misho     368: #endif
1.1       misho     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: 
1.1.1.2 ! misho     384: #if MIN_VERSION(3, 6)
1.1       misho     385:     case 12:
                    386:       return dnsmasq_gostdsa_verify;
                    387: #endif
                    388:       
                    389:     case 13: case 14:
                    390:       return dnsmasq_ecdsa_verify;
1.1.1.2 ! misho     391:       
        !           392: #if MIN_VERSION(3, 1)
        !           393:     case 15:
        !           394:       return dnsmasq_eddsa_verify;
        !           395: #endif
1.1       misho     396: 
1.1.1.2 ! misho     397: #if MIN_VERSION(3, 6)
        !           398:     case 16:
1.1       misho     399:       return dnsmasq_eddsa_verify;
1.1.1.2 ! misho     400: #endif
1.1       misho     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";
1.1.1.2 ! misho     433: #if MIN_VERSION(3, 6)
        !           434:     case 3: return "gosthash94cp";
        !           435: #endif
1.1       misho     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 */
1.1.1.2 ! misho     454: #if MIN_VERSION(3, 6)
        !           455:     case 12: return "gosthash94cp"; /* ECC-GOST */ 
        !           456: #endif
1.1       misho     457:     case 13: return "sha256";     /* ECDSAP256SHA256 */
                    458:     case 14: return "sha384";     /* ECDSAP384SHA384 */        
1.1.1.2 ! misho     459: #if MIN_VERSION(3, 1)
1.1       misho     460:     case 15: return "null_hash";  /* ED25519 */
1.1.1.2 ! misho     461: #  if MIN_VERSION(3, 6)
1.1       misho     462:     case 16: return "null_hash";  /* ED448 */
1.1.1.2 ! misho     463: #  endif
        !           464: #endif
1.1       misho     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: 
1.1.1.2 ! misho     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;
1.1       misho     509: #endif
1.1.1.2 ! misho     510: }
        !           511: 
        !           512: #endif /* defined(HAVE_DNSSEC) || defined(HAVE_CRYPTOHASH) */

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