[BACK]Return to dst_api.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / lib / libresolv

Annotation of src/lib/libresolv/dst_api.c, Revision 1.3

1.3     ! christos    1: /*     $NetBSD: dst_api.c,v 1.2 2012/11/16 02:10:26 joerg Exp $        */
1.1       christos    2:
                      3: /*
                      4:  * Portions Copyright (c) 1995-1998 by Trusted Information Systems, Inc.
                      5:  *
                      6:  * Permission to use, copy modify, and distribute this software for any
                      7:  * purpose with or without fee is hereby granted, provided that the above
                      8:  * copyright notice and this permission notice appear in all copies.
                      9:  *
                     10:  * THE SOFTWARE IS PROVIDED "AS IS" AND TRUSTED INFORMATION SYSTEMS
                     11:  * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL
                     12:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS.  IN NO EVENT SHALL
                     13:  * TRUSTED INFORMATION SYSTEMS BE LIABLE FOR ANY SPECIAL, DIRECT,
                     14:  * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING
                     15:  * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT,
                     16:  * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION
                     17:  * WITH THE USE OR PERFORMANCE OF THE SOFTWARE.
                     18:  */
                     19: /*
                     20:  * This file contains the interface between the DST API and the crypto API.
                     21:  * This is the only file that needs to be changed if the crypto system is
                     22:  * changed.  Exported functions are:
                     23:  * void dst_init()      Initialize the toolkit
                     24:  * int  dst_check_algorithm()   Function to determines if alg is suppored.
                     25:  * int  dst_compare_keys()      Function to compare two keys for equality.
                     26:  * int  dst_sign_data()         Incremental signing routine.
                     27:  * int  dst_verify_data()       Incremental verify routine.
                     28:  * int  dst_generate_key()      Function to generate new KEY
                     29:  * DST_KEY *dst_read_key()      Function to retrieve private/public KEY.
                     30:  * void dst_write_key()         Function to write out a key.
                     31:  * DST_KEY *dst_dnskey_to_key() Function to convert DNS KEY RR to a DST
                     32:  *                             KEY structure.
                     33:  * int dst_key_to_dnskey()     Function to return a public key in DNS
                     34:  *                             format binary
                     35:  * DST_KEY *dst_buffer_to_key() Converst a data in buffer to KEY
                     36:  * int *dst_key_to_buffer()    Writes out DST_KEY key matterial in buffer
                     37:  * void dst_free_key()         Releases all memory referenced by key structure
                     38:  */
                     39: #include <sys/cdefs.h>
                     40: #if 0
                     41: static const char rcsid[] = "Header: /proj/cvs/prod/libbind/dst/dst_api.c,v 1.17 2007/09/24 17:18:25 each Exp ";
                     42: #else
1.3     ! christos   43: __RCSID("$NetBSD: dst_api.c,v 1.2 2012/11/16 02:10:26 joerg Exp $");
1.1       christos   44: #endif
                     45:
                     46:
                     47: #include "port_before.h"
                     48: #include <stdio.h>
                     49: #include <errno.h>
                     50: #include <fcntl.h>
                     51: #include <stdlib.h>
                     52: #include <unistd.h>
                     53: #include <string.h>
                     54: #include <memory.h>
                     55: #include <ctype.h>
                     56: #include <time.h>
                     57: #include <sys/param.h>
                     58: #include <sys/stat.h>
                     59: #include <sys/socket.h>
                     60: #include <netinet/in.h>
                     61: #include <arpa/nameser.h>
                     62: #include <resolv.h>
                     63:
                     64: #include "dst_internal.h"
                     65: #include "port_after.h"
                     66:
                     67: /* static variables */
                     68: static int done_init = 0;
                     69: dst_func *dst_t_func[DST_MAX_ALGS];
                     70: const char *dst_path = "";
                     71:
                     72: /* internal I/O functions */
                     73: static DST_KEY *dst_s_read_public_key(const char *in_name,
                     74:                                      const u_int16_t in_id, int in_alg);
                     75: static int dst_s_read_private_key_file(char *name, DST_KEY *pk_key,
                     76:                                       u_int16_t in_id, int in_alg);
                     77: static int dst_s_write_public_key(const DST_KEY *key);
                     78: static int dst_s_write_private_key(const DST_KEY *key);
                     79:
                     80: /* internal function to set up data structure */
                     81: static DST_KEY *dst_s_get_key_struct(const char *name, const int alg,
                     82:                                     const int flags, const int protocol,
                     83:                                     const int bits);
                     84:
                     85: /*%
                     86:  *  dst_init
                     87:  *     This function initializes the Digital Signature Toolkit.
                     88:  *     Right now, it just checks the DSTKEYPATH environment variable.
                     89:  *  Parameters
                     90:  *     none
                     91:  *  Returns
                     92:  *     none
                     93:  */
                     94: void
                     95: dst_init(void)
                     96: {
                     97:        char *s;
                     98:        size_t len;
                     99:
                    100:        if (done_init != 0)
                    101:                return;
                    102:        done_init = 1;
                    103:
                    104:        s = getenv("DSTKEYPATH");
                    105:        len = 0;
                    106:        if (s) {
                    107:                struct stat statbuf;
                    108:
                    109:                len = strlen(s);
                    110:                if (len > PATH_MAX) {
                    111:                        EREPORT(("%s: %s is longer than %d characters,"
                    112:                            " ignoring\n", __func__, s, PATH_MAX));
                    113:                } else if (stat(s, &statbuf) != 0 ||
                    114:                    !S_ISDIR(statbuf.st_mode)) {
                    115:                        EREPORT(("%s: %s is not a valid directory\n",
                    116:                            __func__, s));
                    117:                } else {
                    118:                        char *tmp;
                    119:                        tmp = (char *) malloc(len + 2);
                    120:                        memcpy(tmp, s, len + 1);
                    121:                        if (tmp[strlen(tmp) - 1] != '/') {
                    122:                                tmp[strlen(tmp) + 1] = 0;
                    123:                                tmp[strlen(tmp)] = '/';
                    124:                        }
                    125:                        dst_path = tmp;
                    126:                }
                    127:        }
                    128:        memset(dst_t_func, 0, sizeof(dst_t_func));
                    129:        /* first one is selected */
                    130:        dst_hmac_md5_init();
                    131: }
                    132:
                    133: /*%
                    134:  *  dst_check_algorithm
                    135:  *     This function determines if the crypto system for the specified
                    136:  *     algorithm is present.
                    137:  *  Parameters
                    138:  *     alg     1       KEY_RSA
                    139:  *             3       KEY_DSA
                    140:  *           157     KEY_HMAC_MD5
                    141:  *                   future algorithms TBD and registered with IANA.
                    142:  *  Returns
                    143:  *     1 - The algorithm is available.
                    144:  *     0 - The algorithm is not available.
                    145:  */
                    146: int
                    147: dst_check_algorithm(const int alg)
                    148: {
                    149:        return (dst_t_func[alg] != NULL);
                    150: }
                    151:
                    152: /*%
                    153:  * dst_s_get_key_struct
                    154:  *     This function allocates key structure and fills in some of the
                    155:  *     fields of the structure.
                    156:  * Parameters:
                    157:  *     name:     the name of the key
                    158:  *     alg:      the algorithm number
                    159:  *     flags:    the dns flags of the key
                    160:  *     protocol: the dns protocol of the key
                    161:  *     bits:     the size of the key
                    162:  * Returns:
                    163:  *       NULL if error
                    164:  *       valid pointer otherwise
                    165:  */
                    166: static DST_KEY *
                    167: dst_s_get_key_struct(const char *name, const int alg, const int flags,
                    168:                     const int protocol, const int bits)
                    169: {
                    170:        DST_KEY *new_key = NULL;
                    171:
                    172:        if (dst_check_algorithm(alg)) /*%< make sure alg is available */
                    173:                new_key = (DST_KEY *) malloc(sizeof(*new_key));
                    174:        if (new_key == NULL)
                    175:                return (NULL);
                    176:
                    177:        memset(new_key, 0, sizeof(*new_key));
                    178:        new_key->dk_key_name = strdup(name);
                    179:        if (new_key->dk_key_name == NULL) {
                    180:                free(new_key);
                    181:                return (NULL);
                    182:        }
                    183:        new_key->dk_alg = alg;
                    184:        new_key->dk_flags = flags;
                    185:        new_key->dk_proto = protocol;
                    186:        new_key->dk_KEY_struct = NULL;
                    187:        new_key->dk_key_size = bits;
                    188:        new_key->dk_func = dst_t_func[alg];
                    189:        return (new_key);
                    190: }
                    191:
                    192: /*%
                    193:  *  dst_compare_keys
                    194:  *     Compares two keys for equality.
                    195:  *  Parameters
                    196:  *     key1, key2      Two keys to be compared.
                    197:  *  Returns
                    198:  *     0              The keys are equal.
                    199:  *     non-zero        The keys are not equal.
                    200:  */
                    201:
                    202: int
                    203: dst_compare_keys(const DST_KEY *key1, const DST_KEY *key2)
                    204: {
                    205:        if (key1 == key2)
                    206:                return (0);
                    207:        if (key1 == NULL || key2 == NULL)
                    208:                return (4);
                    209:        if (key1->dk_alg != key2->dk_alg)
                    210:                return (1);
                    211:        if (key1->dk_key_size != key2->dk_key_size)
                    212:                return (2);
                    213:        if (key1->dk_id != key2->dk_id)
                    214:                return (3);
                    215:        return (key1->dk_func->compare(key1, key2));
                    216: }
                    217:
                    218: /*%
                    219:  * dst_sign_data
                    220:  *     An incremental signing function.  Data is signed in steps.
                    221:  *     First the context must be initialized (SIG_MODE_INIT).
                    222:  *     Then data is hashed (SIG_MODE_UPDATE).  Finally the signature
                    223:  *     itself is created (SIG_MODE_FINAL).  This function can be called
                    224:  *     once with INIT, UPDATE and FINAL modes all set, or it can be
                    225:  *     called separately with a different mode set for each step.  The
                    226:  *     UPDATE step can be repeated.
                    227:  * Parameters
                    228:  *     mode    A bit mask used to specify operation(s) to be performed.
                    229:  *               SIG_MODE_INIT    1   Initialize digest
                    230:  *               SIG_MODE_UPDATE        2   Add data to digest
                    231:  *               SIG_MODE_FINAL          4   Generate signature
                    232:  *                                           from signature
                    233:  *               SIG_MODE_ALL (SIG_MODE_INIT,SIG_MODE_UPDATE,SIG_MODE_FINAL
                    234:  *     data    Data to be signed.
                    235:  *     len     The length in bytes of data to be signed.
                    236:  *     in_key  Contains a private key to sign with.
                    237:  *               KEY structures should be handled (created, converted,
                    238:  *               compared, stored, freed) by the DST.
                    239:  *     signature
                    240:  *           The location to which the signature will be written.
                    241:  *     sig_len Length of the signature field in bytes.
                    242:  * Return
                    243:  *      0      Successfull INIT or Update operation
                    244:  *     &gt;0      success FINAL (sign) operation
                    245:  *     &lt;0      failure
                    246:  */
                    247:
                    248: int
                    249: dst_sign_data(const int mode, DST_KEY *in_key, void **context,
                    250:              const u_char *data, const int len,
                    251:              u_char *signature, const int sig_len)
                    252: {
                    253:        DUMP(data, mode, len, "dst_sign_data()");
                    254:
                    255:        if (mode & SIG_MODE_FINAL &&
                    256:            (in_key->dk_KEY_struct == NULL || signature == NULL))
                    257:                return (MISSING_KEY_OR_SIGNATURE);
                    258:
                    259:        if (in_key->dk_func && in_key->dk_func->sign)
                    260:                return (in_key->dk_func->sign(mode, in_key, context, data, len,
                    261:                                              signature, sig_len));
                    262:        return (UNKNOWN_KEYALG);
                    263: }
                    264:
                    265: /*%
                    266:  *  dst_verify_data
                    267:  *     An incremental verify function.  Data is verified in steps.
                    268:  *     First the context must be initialized (SIG_MODE_INIT).
                    269:  *     Then data is hashed (SIG_MODE_UPDATE).  Finally the signature
                    270:  *     is verified (SIG_MODE_FINAL).  This function can be called
                    271:  *     once with INIT, UPDATE and FINAL modes all set, or it can be
                    272:  *     called separately with a different mode set for each step.  The
                    273:  *     UPDATE step can be repeated.
                    274:  *  Parameters
                    275:  *     mode    Operations to perform this time.
                    276:  *                   SIG_MODE_INIT       1   Initialize digest
                    277:  *                   SIG_MODE_UPDATE     2   add data to digest
                    278:  *                   SIG_MODE_FINAL      4   verify signature
                    279:  *                   SIG_MODE_ALL
                    280:  *                       (SIG_MODE_INIT,SIG_MODE_UPDATE,SIG_MODE_FINAL)
                    281:  *     data    Data to pass through the hash function.
                    282:  *     len      Length of the data in bytes.
                    283:  *     in_key      Key for verification.
                    284:  *     signature   Location of signature.
                    285:  *     sig_len     Length of the signature in bytes.
                    286:  *  Returns
                    287:  *     0          Verify success
                    288:  *     Non-Zero    Verify Failure
                    289:  */
                    290:
                    291: int
                    292: dst_verify_data(const int mode, DST_KEY *in_key, void **context,
                    293:                const u_char *data, const int len,
                    294:                const u_char *signature, const int sig_len)
                    295: {
                    296:        DUMP(data, mode, len, "dst_verify_data()");
                    297:        if (mode & SIG_MODE_FINAL &&
                    298:            (in_key->dk_KEY_struct == NULL || signature == NULL))
                    299:                return (MISSING_KEY_OR_SIGNATURE);
                    300:
                    301:        if (in_key->dk_func == NULL || in_key->dk_func->verify == NULL)
                    302:                return (UNSUPPORTED_KEYALG);
                    303:        return (in_key->dk_func->verify(mode, in_key, context, data, len,
                    304:                                        signature, sig_len));
                    305: }
                    306:
                    307: /*%
                    308:  *  dst_read_private_key
                    309:  *     Access a private key.  First the list of private keys that have
                    310:  *     already been read in is searched, then the key accessed on disk.
                    311:  *     If the private key can be found, it is returned.  If the key cannot
                    312:  *     be found, a null pointer is returned.  The options specify required
                    313:  *     key characteristics.  If the private key requested does not have
                    314:  *     these characteristics, it will not be read.
                    315:  *  Parameters
                    316:  *     in_keyname  The private key name.
                    317:  *     in_id       The id of the private key.
                    318:  *     options     DST_FORCE_READ  Read from disk - don't use a previously
                    319:  *                                   read key.
                    320:  *               DST_CAN_SIGN    The key must be useable for signing.
                    321:  *               DST_NO_AUTHEN   The key must be useable for authentication.
                    322:  *               DST_STANDARD    Return any key
                    323:  *  Returns
                    324:  *     NULL    If there is no key found in the current directory or
                    325:  *                   this key has not been loaded before.
                    326:  *     !NULL       Success - KEY structure returned.
                    327:  */
                    328:
                    329: DST_KEY *
                    330: dst_read_key(const char *in_keyname, const u_int16_t in_id,
                    331:             const int in_alg, const int type)
                    332: {
                    333:        char keyname[PATH_MAX];
                    334:        DST_KEY *dg_key = NULL, *pubkey = NULL;
                    335:
                    336:        if (!dst_check_algorithm(in_alg)) { /*%< make sure alg is available */
                    337:                EREPORT(("%s: Algorithm %d not suppored\n", __func__, in_alg));
                    338:                return (NULL);
                    339:        }
                    340:        if ((type & (DST_PUBLIC | DST_PRIVATE)) == 0)
                    341:                return (NULL);
                    342:        if (in_keyname == NULL) {
                    343:                EREPORT(("%s: Null key name passed in\n", __func__));
                    344:                return (NULL);
                    345:        } else if (strlen(in_keyname) >= sizeof(keyname)) {
                    346:                EREPORT(("%s: keyname too big\n", __func__));
                    347:                return (NULL);
                    348:        } else
                    349:                strcpy(keyname, in_keyname);
                    350:
                    351:        /* before I read in the public key, check if it is allowed to sign */
                    352:        if ((pubkey = dst_s_read_public_key(keyname, in_id, in_alg)) == NULL)
                    353:                return (NULL);
                    354:
                    355:        if (type == DST_PUBLIC)
                    356:                return pubkey;
                    357:
                    358:        if (!(dg_key = dst_s_get_key_struct(keyname, pubkey->dk_alg,
                    359:                                            (int)pubkey->dk_flags,
                    360:                                            pubkey->dk_proto, 0)))
                    361:                return (dg_key);
                    362:        /* Fill in private key and some fields in the general key structure */
                    363:        if (dst_s_read_private_key_file(keyname, dg_key, pubkey->dk_id,
                    364:                                        pubkey->dk_alg) == 0)
                    365:                dg_key = dst_free_key(dg_key);
                    366:
                    367:        (void)dst_free_key(pubkey);
                    368:        return (dg_key);
                    369: }
                    370:
                    371: int
                    372: dst_write_key(const DST_KEY *key, const int type)
                    373: {
                    374:        int pub = 0, priv = 0;
                    375:
                    376:        if (key == NULL)
                    377:                return (0);
                    378:        if (!dst_check_algorithm(key->dk_alg)) { /*%< make sure alg is available */
                    379:                EREPORT(("%s: Algorithm %d not suppored\n", __func__,
                    380:                    key->dk_alg));
                    381:                return (UNSUPPORTED_KEYALG);
                    382:        }
                    383:        if ((type & (DST_PRIVATE|DST_PUBLIC)) == 0)
                    384:                return (0);
                    385:
                    386:        if (type & DST_PUBLIC)
                    387:                if ((pub = dst_s_write_public_key(key)) < 0)
                    388:                        return (pub);
                    389:        if (type & DST_PRIVATE)
                    390:                if ((priv = dst_s_write_private_key(key)) < 0)
                    391:                        return (priv);
                    392:        return (priv+pub);
                    393: }
                    394:
                    395: /*%
                    396:  *  dst_write_private_key
                    397:  *     Write a private key to disk.  The filename will be of the form:
                    398:  *     K&lt;key-&gt;dk_name&gt;+&lt;key-&gt;dk_alg+&gt;&lt;key-d&gt;k_id.&gt;&lt;private key suffix&gt;.
                    399:  *     If there is already a file with this name, an error is returned.
                    400:  *
                    401:  *  Parameters
                    402:  *     key     A DST managed key structure that contains
                    403:  *           all information needed about a key.
                    404:  *  Return
                    405:  *     &gt;= 0    Correct behavior.  Returns length of encoded key value
                    406:  *               written to disk.
                    407:  *     &lt;  0    error.
                    408:  */
                    409:
                    410: static int
                    411: dst_s_write_private_key(const DST_KEY *key)
                    412: {
                    413:        u_char encoded_block[RAW_KEY_SIZE];
                    414:        char file[PATH_MAX];
                    415:        int len;
                    416:        FILE *fp;
                    417:
                    418:        /* First encode the key into the portable key format */
                    419:        if (key == NULL)
                    420:                return (-1);
                    421:        if (key->dk_KEY_struct == NULL)
                    422:                return (0);     /*%< null key has no private key */
                    423:        if (key->dk_func == NULL || key->dk_func->to_file_fmt == NULL) {
                    424:                EREPORT(("%s: Unsupported operation %d\n", __func__,
                    425:                    key->dk_alg));
                    426:                return (-5);
                    427:        } else if ((len = key->dk_func->to_file_fmt(key, (char *)encoded_block,
                    428:                                         (int)sizeof(encoded_block))) <= 0) {
                    429:                EREPORT(("%s: Failed encoding private RSA bsafe key %d\n",
                    430:                    __func__, len));
                    431:                return (-8);
                    432:        }
                    433:        /* Now I can create the file I want to use */
                    434:        dst_s_build_filename(file, key->dk_key_name, key->dk_id, key->dk_alg,
                    435:                             PRIVATE_KEY, PATH_MAX);
                    436:
                    437:        /* Do not overwrite an existing file */
                    438:        if ((fp = dst_s_fopen(file, "w", 0600)) != NULL) {
                    439:                ssize_t nn;
1.3     ! christos  440:                nn = fwrite(encoded_block, 1, len, fp);
        !           441:                if (nn != len) {
1.1       christos  442:                        EREPORT(("%s: Write failure on %s %d != %zd"
                    443:                            " errno=%d\n", __func__, file, len, nn, errno));
1.3     ! christos  444:
1.1       christos  445:                        fclose(fp);
                    446:                        return (-5);
                    447:                }
                    448:                fclose(fp);
                    449:        } else {
                    450:                EREPORT(("%s: Can not create file %s\n", __func__,
                    451:                    file));
                    452:                return (-6);
                    453:        }
                    454:        memset(encoded_block, 0, len);
                    455:        return (len);
                    456: }
                    457:
                    458: /*%
                    459: *
                    460:  *  dst_read_public_key
                    461:  *     Read a public key from disk and store in a DST key structure.
                    462:  *  Parameters
                    463:  *     in_name  K&lt;in_name&gt;&lt;in_id&gt;.&lt;public key suffix&gt; is the
                    464:  *                   filename of the key file to be read.
                    465:  *  Returns
                    466:  *     NULL        If the key does not exist or no name is supplied.
                    467:  *     NON-NULL        Initialized key structure if the key exists.
                    468:  */
                    469:
                    470: static DST_KEY *
                    471: dst_s_read_public_key(const char *in_name, const u_int16_t in_id, int in_alg)
                    472: {
                    473:        int flags, proto, alg, dlen;
                    474:        size_t len;
                    475:        int c;
                    476:        char name[PATH_MAX], enckey[RAW_KEY_SIZE], *notspace;
                    477:        u_char deckey[RAW_KEY_SIZE];
                    478:        FILE *fp;
                    479:
                    480:        if (in_name == NULL) {
                    481:                EREPORT(("%s: No key name given\n", __func__));
                    482:                return (NULL);
                    483:        }
                    484:        if (dst_s_build_filename(name, in_name, in_id, in_alg, PUBLIC_KEY,
                    485:                                 PATH_MAX) == -1) {
                    486:                EREPORT(("%s: Cannot make filename from %s, %d, and %s\n",
                    487:                    __func__, in_name, in_id, PUBLIC_KEY));
                    488:                return (NULL);
                    489:        }
                    490:        /*
                    491:         * Open the file and read it's formatted contents up to key
                    492:         * File format:
                    493:         *    domain.name [ttl] [IN] KEY  &lt;flags&gt; &lt;protocol&gt; &lt;algorithm&gt; &lt;key&gt;
                    494:         * flags, proto, alg stored as decimal (or hex numbers FIXME).
                    495:         * (FIXME: handle parentheses for line continuation.)
                    496:         */
                    497:        if ((fp = dst_s_fopen(name, "r", 0)) == NULL) {
                    498:                EREPORT(("%s: Public Key not found %s\n", __func__, name));
                    499:                return (NULL);
                    500:        }
                    501:        /* Skip domain name, which ends at first blank */
                    502:        while ((c = getc(fp)) != EOF)
                    503:                if (isspace(c))
                    504:                        break;
                    505:        /* Skip blank to get to next field */
                    506:        while ((c = getc(fp)) != EOF)
                    507:                if (!isspace(c))
                    508:                        break;
                    509:
                    510:        /* Skip optional TTL -- if initial digit, skip whole word. */
                    511:        if (isdigit(c)) {
                    512:                while ((c = getc(fp)) != EOF)
                    513:                        if (isspace(c))
                    514:                                break;
                    515:                while ((c = getc(fp)) != EOF)
                    516:                        if (!isspace(c))
                    517:                                break;
                    518:        }
                    519:        /* Skip optional "IN" */
                    520:        if (c == 'I' || c == 'i') {
                    521:                while ((c = getc(fp)) != EOF)
                    522:                        if (isspace(c))
                    523:                                break;
                    524:                while ((c = getc(fp)) != EOF)
                    525:                        if (!isspace(c))
                    526:                                break;
                    527:        }
                    528:        /* Locate and skip "KEY" */
                    529:        if (c != 'K' && c != 'k') {
                    530:                EREPORT(("%s: \"KEY\" doesn't appear in file: %s", __func__,
                    531:                    name));
                    532:                return NULL;
                    533:        }
                    534:        while ((c = getc(fp)) != EOF)
                    535:                if (isspace(c))
                    536:                        break;
                    537:        while ((c = getc(fp)) != EOF)
                    538:                if (!isspace(c))
                    539:                        break;
                    540:        ungetc(c, fp);          /*%< return the charcter to the input field */
                    541:        /* Handle hex!! FIXME.  */
                    542:
                    543:        if (fscanf(fp, "%d %d %d", &flags, &proto, &alg) != 3) {
                    544:                EREPORT(("%s: Can not read flag/proto/alg field from %s\n",
                    545:                    __func__, name));
                    546:                return (NULL);
                    547:        }
                    548:        /* read in the key string */
                    549:        fgets(enckey, (int)sizeof(enckey), fp);
                    550:
                    551:        /* If we aren't at end-of-file, something is wrong.  */
                    552:        while ((c = getc(fp)) != EOF)
                    553:                if (!isspace(c))
                    554:                        break;
                    555:        if (!feof(fp)) {
                    556:                EREPORT(("%s: Key too long in file: %s", __func__, name));
                    557:                return NULL;
                    558:        }
                    559:        fclose(fp);
                    560:
                    561:        if ((len = strlen(enckey)) == 0)
                    562:                return (NULL);
                    563:
                    564:        /* discard \n */
                    565:        enckey[--len] = '\0';
                    566:
                    567:        /* remove leading spaces */
                    568:        for (notspace = (char *) enckey; isspace((*notspace)&0xff); len--)
                    569:                notspace++;
                    570:
                    571:        dlen = b64_pton(notspace, deckey, sizeof(deckey));
                    572:        if (dlen < 0) {
                    573:                EREPORT(("%s: bad return from b64_pton = %d", __func__, dlen));
                    574:                return (NULL);
                    575:        }
                    576:        /* store key and info in a key structure that is returned */
                    577: /*     return dst_store_public_key(in_name, alg, proto, 666, flags, deckey,
                    578:                                    dlen);*/
                    579:        return dst_buffer_to_key(in_name, alg, flags, proto, deckey, dlen);
                    580: }
                    581:
                    582: /*%
                    583:  *  dst_write_public_key
                    584:  *     Write a key to disk in DNS format.
                    585:  *  Parameters
                    586:  *     key     Pointer to a DST key structure.
                    587:  *  Returns
                    588:  *     0       Failure
                    589:  *     1       Success
                    590:  */
                    591:
                    592: static int
                    593: dst_s_write_public_key(const DST_KEY *key)
                    594: {
                    595:        FILE *fp;
                    596:        char filename[PATH_MAX];
                    597:        u_char out_key[RAW_KEY_SIZE];
                    598:        char enc_key[RAW_KEY_SIZE];
                    599:        int len = 0;
                    600:        int mode;
                    601:
                    602:        memset(out_key, 0, sizeof(out_key));
                    603:        if (key == NULL) {
                    604:                EREPORT(("%s: No key specified \n", __func__));
                    605:                return (0);
                    606:        } else if ((len = dst_key_to_dnskey(key, out_key,
                    607:            (int)sizeof(out_key)))< 0)
                    608:                return (0);
                    609:
                    610:        /* Make the filename */
                    611:        if (dst_s_build_filename(filename, key->dk_key_name, key->dk_id,
                    612:                                 key->dk_alg, PUBLIC_KEY, PATH_MAX) == -1) {
                    613:                EREPORT(("%s: Cannot make filename from %s, %d, and %s\n",
                    614:                    __func__, key->dk_key_name, key->dk_id, PUBLIC_KEY));
                    615:                return (0);
                    616:        }
                    617:        /* XXX in general this should be a check for symmetric keys */
                    618:        mode = (key->dk_alg == KEY_HMAC_MD5) ? 0600 : 0644;
                    619:        /* create public key file */
                    620:        if ((fp = dst_s_fopen(filename, "w+", mode)) == NULL) {
                    621:                EREPORT(("%s: open of file:%s failed (errno=%d)\n",
                    622:                    __func__, filename, errno));
                    623:                return (0);
                    624:        }
                    625:        /*write out key first base64 the key data */
                    626:        if (key->dk_flags & DST_EXTEND_FLAG)
                    627:                b64_ntop(&out_key[6], len - 6, enc_key, sizeof(enc_key));
                    628:        else
                    629:                b64_ntop(&out_key[4], len - 4, enc_key, sizeof(enc_key));
                    630:        fprintf(fp, "%s IN KEY %d %d %d %s\n",
                    631:                key->dk_key_name,
                    632:                key->dk_flags, key->dk_proto, key->dk_alg, enc_key);
                    633:        fclose(fp);
                    634:        return (1);
                    635: }
                    636:
                    637: /*%
                    638:  *  dst_dnskey_to_public_key
                    639:  *     This function converts the contents of a DNS KEY RR into a DST
                    640:  *     key structure.
                    641:  *  Paramters
                    642:  *     len      Length of the RDATA of the KEY RR RDATA
                    643:  *     rdata    A pointer to the the KEY RR RDATA.
                    644:  *     in_name     Key name to be stored in key structure.
                    645:  *  Returns
                    646:  *     NULL        Failure
                    647:  *     NON-NULL        Success.  Pointer to key structure.
                    648:  *                     Caller's responsibility to free() it.
                    649:  */
                    650:
                    651: DST_KEY *
                    652: dst_dnskey_to_key(const char *in_name, const u_char *rdata, const int len)
                    653: {
                    654:        DST_KEY *key_st;
                    655:        int alg ;
                    656:        int start = DST_KEY_START;
                    657:
                    658:        if (rdata == NULL || len <= DST_KEY_ALG) /*%< no data */
                    659:                return (NULL);
                    660:        alg = (u_int8_t) rdata[DST_KEY_ALG];
                    661:        if (!dst_check_algorithm(alg)) { /*%< make sure alg is available */
                    662:                EREPORT(("%s: Algorithm %d not suppored\n", __func__,
                    663:                    alg));
                    664:                return (NULL);
                    665:        }
                    666:
                    667:        if (in_name == NULL)
                    668:                return (NULL);
                    669:
                    670:        if ((key_st = dst_s_get_key_struct(in_name, alg, 0, 0, 0)) == NULL)
                    671:                return (NULL);
                    672:
                    673:        key_st->dk_id = dst_s_dns_key_id(rdata, len);
                    674:        key_st->dk_flags = dst_s_get_int16(rdata);
                    675:        key_st->dk_proto = (u_int16_t) rdata[DST_KEY_PROT];
                    676:        if (key_st->dk_flags & DST_EXTEND_FLAG) {
                    677:                u_int32_t ext_flags;
                    678:                ext_flags = (u_int32_t) dst_s_get_int16(&rdata[DST_EXT_FLAG]);
                    679:                key_st->dk_flags = key_st->dk_flags | (ext_flags << 16);
                    680:                start += 2;
                    681:        }
                    682:        /*
                    683:         * now point to the begining of the data representing the encoding
                    684:         * of the key
                    685:         */
                    686:        if (key_st->dk_func && key_st->dk_func->from_dns_key) {
                    687:                if (key_st->dk_func->from_dns_key(key_st, &rdata[start],
                    688:                                                  len - start) > 0)
                    689:                        return (key_st);
                    690:        } else
                    691:                EREPORT(("%s: unsuppored alg %d\n", __func__,
                    692:                         alg));
                    693:
                    694:        SAFE_FREE(key_st);
1.2       joerg     695:        return (NULL);
1.1       christos  696: }
                    697:
                    698: /*%
                    699:  *  dst_public_key_to_dnskey
                    700:  *     Function to encode a public key into DNS KEY wire format
                    701:  *  Parameters
                    702:  *     key          Key structure to encode.
                    703:  *     out_storage     Location to write the encoded key to.
                    704:  *     out_len  Size of the output array.
                    705:  *  Returns
                    706:  *     <0      Failure
                    707:  *     >=0     Number of bytes written to out_storage
                    708:  */
                    709:
                    710: int
                    711: dst_key_to_dnskey(const DST_KEY *key, u_char *out_storage,
                    712:                         const int out_len)
                    713: {
                    714:        u_int16_t val;
                    715:        int loc = 0;
                    716:        int enc_len = 0;
                    717:        if (key == NULL)
                    718:                return (-1);
                    719:
                    720:        if (!dst_check_algorithm(key->dk_alg)) { /*%< make sure alg is available */
                    721:                EREPORT(("%s: Algorithm %d not suppored\n", __func__,
                    722:                    key->dk_alg));
                    723:                return (UNSUPPORTED_KEYALG);
                    724:        }
                    725:        memset(out_storage, 0, out_len);
                    726:        val = (u_int16_t)(key->dk_flags & 0xffff);
                    727:        dst_s_put_int16(out_storage, val);
                    728:        loc += 2;
                    729:
                    730:        out_storage[loc++] = (u_char) key->dk_proto;
                    731:        out_storage[loc++] = (u_char) key->dk_alg;
                    732:
                    733:        if (key->dk_flags > 0xffff) {   /*%< Extended flags */
                    734:                val = (u_int16_t)((key->dk_flags >> 16) & 0xffff);
                    735:                dst_s_put_int16(&out_storage[loc], val);
                    736:                loc += 2;
                    737:        }
                    738:        if (key->dk_KEY_struct == NULL)
                    739:                return (loc);
                    740:        if (key->dk_func && key->dk_func->to_dns_key) {
                    741:                enc_len = key->dk_func->to_dns_key(key,
                    742:                                                 (u_char *) &out_storage[loc],
                    743:                                                   out_len - loc);
                    744:                if (enc_len > 0)
                    745:                        return (enc_len + loc);
                    746:                else
                    747:                        return (-1);
                    748:        } else
                    749:                EREPORT(("%s: Unsupported ALG %d\n", __func__, key->dk_alg));
                    750:        return (-1);
                    751: }
                    752:
                    753: /*%
                    754:  *  dst_buffer_to_key
                    755:  *     Function to encode a string of raw data into a DST key
                    756:  *  Parameters
                    757:  *     alg             The algorithm (HMAC only)
                    758:  *     key             A pointer to the data
                    759:  *     keylen          The length of the data
                    760:  *  Returns
                    761:  *     NULL        an error occurred
                    762:  *     NON-NULL        the DST key
                    763:  */
                    764: DST_KEY *
                    765: dst_buffer_to_key(const char *key_name,                /*!< name of the key  */
                    766:                  const int alg,                /*!< algorithm  */
                    767:                  const int flags,              /*!< dns flags  */
                    768:                  const int protocol,           /*!< dns protocol  */
                    769:                  const u_char *key_buf,        /*!< key in dns wire fmt  */
                    770:                  const int key_len)            /*!< size of key  */
                    771: {
                    772:
                    773:        DST_KEY *dkey = NULL;
                    774:        int dnslen;
                    775:        u_char dns[2048];
                    776:
                    777:        if (!dst_check_algorithm(alg)) { /*%< make sure alg is available */
                    778:                EREPORT(("%s: Algorithm %d not suppored\n", __func__, alg));
                    779:                return (NULL);
                    780:        }
                    781:
                    782:        dkey = dst_s_get_key_struct(key_name, alg, flags, protocol, -1);
                    783:
                    784:        if (dkey == NULL || dkey->dk_func == NULL ||
                    785:            dkey->dk_func->from_dns_key == NULL)
                    786:                return (dst_free_key(dkey));
                    787:
                    788:        if (dkey->dk_func->from_dns_key(dkey, key_buf, key_len) < 0) {
                    789:                EREPORT(("%s: dst_buffer_to_hmac failed\n", __func__));
                    790:                return (dst_free_key(dkey));
                    791:        }
                    792:
                    793:        dnslen = dst_key_to_dnskey(dkey, dns, (int)sizeof(dns));
                    794:        dkey->dk_id = dst_s_dns_key_id(dns, dnslen);
                    795:        return (dkey);
                    796: }
                    797:
                    798: int
                    799: dst_key_to_buffer(DST_KEY *key, u_char *out_buff, int buf_len)
                    800: {
                    801:        int len;
                    802:   /* this function will extrac the secret of HMAC into a buffer */
                    803:        if (key == NULL)
                    804:                return (0);
                    805:        if (key->dk_func != NULL && key->dk_func->to_dns_key != NULL) {
                    806:                len = key->dk_func->to_dns_key(key, out_buff, buf_len);
                    807:                if (len < 0)
                    808:                        return (0);
                    809:                return (len);
                    810:        }
                    811:        return (0);
                    812: }
                    813:
                    814: /*%
                    815:  * dst_s_read_private_key_file
                    816:  *     Function reads in private key from a file.
                    817:  *     Fills out the KEY structure.
                    818:  * Parameters
                    819:  *     name    Name of the key to be read.
                    820:  *     pk_key  Structure that the key is returned in.
                    821:  *     in_id   Key identifier (tag)
                    822:  * Return
                    823:  *     1 if everthing works
                    824:  *     0 if there is any problem
                    825:  */
                    826:
                    827: static int
                    828: dst_s_read_private_key_file(char *name, DST_KEY *pk_key, u_int16_t in_id,
                    829:                            int in_alg)
                    830: {
                    831:        int alg, major, minor, file_major, file_minor;
                    832:        ssize_t cnt;
                    833:        size_t len;
                    834:        int ret, id;
                    835:        char filename[PATH_MAX];
                    836:        u_char in_buff[RAW_KEY_SIZE], *p;
                    837:        FILE *fp;
                    838:        int dnslen;
                    839:        u_char dns[2048];
                    840:
                    841:        if (name == NULL || pk_key == NULL) {
                    842:                EREPORT(("%s: No key name given\n", __func__));
                    843:                return (0);
                    844:        }
                    845:        /* Make the filename */
                    846:        if (dst_s_build_filename(filename, name, in_id, in_alg, PRIVATE_KEY,
                    847:                                 PATH_MAX) == -1) {
                    848:                EREPORT(("%s: Cannot make filename from %s, %d, and %s\n",
                    849:                    __func__, name, in_id, PRIVATE_KEY));
                    850:                return (0);
                    851:        }
                    852:        /* first check if we can find the key file */
                    853:        if ((fp = dst_s_fopen(filename, "r", 0)) == NULL) {
                    854:                EREPORT(("%s: Could not open file %s in directory %s\n",
                    855:                    __func__, filename, dst_path[0] ? dst_path :
                    856:                    getcwd(NULL, PATH_MAX - 1)));
                    857:                return (0);
                    858:        }
                    859:        /* now read the header info from the file */
                    860:        if ((cnt = fread(in_buff, 1, sizeof(in_buff), fp)) < 5) {
                    861:                fclose(fp);
                    862:                EREPORT(("%s: error reading file %s (empty file)\n",
                    863:                    __func__, filename));
                    864:                return (0);
                    865:        }
                    866:        len = cnt;
                    867:        /* decrypt key */
                    868:        fclose(fp);
                    869:        if (memcmp(in_buff, "Private-key-format: v", 20) != 0)
                    870:                goto fail;
                    871:        p = in_buff;
                    872:
                    873:        if (!dst_s_verify_str((const char **) (void *)&p,
                    874:                               "Private-key-format: v")) {
                    875:                EREPORT(("%s: Not a Key file/Decrypt failed %s\n", __func__,
                    876:                    name));
                    877:                goto fail;
                    878:        }
                    879:        /* read in file format */
                    880:        sscanf((char *)p, "%d.%d", &file_major, &file_minor);
                    881:        sscanf(KEY_FILE_FORMAT, "%d.%d", &major, &minor);
                    882:        if (file_major < 1) {
                    883:                EREPORT(("%s: Unknown keyfile %d.%d version for %s\n",
                    884:                    __func__, file_major, file_minor, name));
                    885:                goto fail;
                    886:        } else if (file_major > major || file_minor > minor)
                    887:                EREPORT(("%s: Keyfile %s version higher than mine %d.%d MAY"
                    888:                    " FAIL\n", __func__, name, file_major, file_minor));
                    889:
                    890:        while (*p++ != '\n') ;  /*%< skip to end of line */
                    891:
                    892:        if (!dst_s_verify_str((const char **) (void *)&p, "Algorithm: "))
                    893:                goto fail;
                    894:
                    895:        if (sscanf((char *)p, "%d", &alg) != 1)
                    896:                goto fail;
                    897:        while (*p++ != '\n') ;  /*%< skip to end of line */
                    898:
                    899:        if (pk_key->dk_key_name && !strcmp(pk_key->dk_key_name, name))
                    900:                SAFE_FREE2(pk_key->dk_key_name, strlen(pk_key->dk_key_name));
                    901:        pk_key->dk_key_name = strdup(name);
                    902:
                    903:        /* allocate and fill in key structure */
                    904:        if (pk_key->dk_func == NULL || pk_key->dk_func->from_file_fmt == NULL)
                    905:                goto fail;
                    906:
                    907:        ret = pk_key->dk_func->from_file_fmt(pk_key, (char *)p,
                    908:            (int)(&in_buff[len] - p));
                    909:        if (ret < 0)
                    910:                goto fail;
                    911:
                    912:        dnslen = dst_key_to_dnskey(pk_key, dns, (int)sizeof(dns));
                    913:        id = dst_s_dns_key_id(dns, dnslen);
                    914:
                    915:        /* Make sure the actual key tag matches the input tag used in the
                    916:         * filename */
                    917:        if (id != in_id) {
                    918:                EREPORT(("%s: actual tag of key read %d != input tag used to"
                    919:                    "build filename %d.\n", __func__, id, in_id));
                    920:                goto fail;
                    921:        }
                    922:        pk_key->dk_id = (u_int16_t) id;
                    923:        pk_key->dk_alg = alg;
                    924:        memset(in_buff, 0, len);
                    925:        return (1);
                    926:
                    927:  fail:
                    928:        memset(in_buff, 0, len);
                    929:        return (0);
                    930: }
                    931:
                    932: /*%
                    933:  *     Generate and store a public/private keypair.
                    934:  *     Keys will be stored in formatted files.
                    935:  *
                    936:  *  Parameters
                    937:  &
                    938:  *\par name    Name of the new key.  Used to create key files
                    939:  *\li            K&lt;name&gt;+&lt;alg&gt;+&lt;id&gt;.public and K&lt;name&gt;+&lt;alg&gt;+&lt;id&gt;.private.
                    940:  *\par bits    Size of the new key in bits.
                    941:  *\par exp     What exponent to use:
                    942:  *\li            0        use exponent 3
                    943:  *\li            non-zero    use Fermant4
                    944:  *\par flags   The default value of the DNS Key flags.
                    945:  *\li            The DNS Key RR Flag field is defined in RFC2065,
                    946:  *               section 3.3.  The field has 16 bits.
                    947:  *\par protocol
                    948:  *\li        Default value of the DNS Key protocol field.
                    949:  *\li            The DNS Key protocol field is defined in RFC2065,
                    950:  *               section 3.4.  The field has 8 bits.
                    951:  *\par alg     What algorithm to use.  Currently defined:
                    952:  *\li            KEY_RSA       1
                    953:  *\li            KEY_DSA       3
                    954:  *\li            KEY_HMAC    157
                    955:  *\par out_id The key tag is returned.
                    956:  *
                    957:  *  Return
                    958:  *\li  NULL            Failure
                    959:  *\li  non-NULL        the generated key pair
                    960:  *                     Caller frees the result, and its dk_name pointer.
                    961:  */
                    962: DST_KEY *
                    963: dst_generate_key(const char *name, const int bits, const int exp,
                    964:                 const int flags, const int protocol, const int alg)
                    965: {
                    966:        DST_KEY *new_key = NULL;
                    967:        int dnslen;
                    968:        u_char dns[2048];
                    969:
                    970:        if (name == NULL)
                    971:                return (NULL);
                    972:
                    973:        if (!dst_check_algorithm(alg)) { /*%< make sure alg is available */
                    974:                EREPORT(("%s: Algorithm %d not suppored\n", __func__, alg));
                    975:                return (NULL);
                    976:        }
                    977:
                    978:        new_key = dst_s_get_key_struct(name, alg, flags, protocol, bits);
                    979:        if (new_key == NULL)
                    980:                return (NULL);
                    981:        if (bits == 0) /*%< null key we are done */
                    982:                return (new_key);
                    983:        if (new_key->dk_func == NULL || new_key->dk_func->generate == NULL) {
                    984:                EREPORT(("%s: Unsupported algorithm %d\n", __func__, alg));
                    985:                return (dst_free_key(new_key));
                    986:        }
                    987:        if (new_key->dk_func->generate(new_key, exp) <= 0) {
                    988:                EREPORT(("%s: Key generation failure %s %d %d %d\n", __func__,
                    989:                    new_key->dk_key_name, new_key->dk_alg,
                    990:                    new_key->dk_key_size, exp));
                    991:                return (dst_free_key(new_key));
                    992:        }
                    993:
                    994:        dnslen = dst_key_to_dnskey(new_key, dns, (int)sizeof(dns));
                    995:        if (dnslen != UNSUPPORTED_KEYALG)
                    996:                new_key->dk_id = dst_s_dns_key_id(dns, dnslen);
                    997:        else
                    998:                new_key->dk_id = 0;
                    999:
                   1000:        return (new_key);
                   1001: }
                   1002:
                   1003: /*%
                   1004:  *     Release all data structures pointed to by a key structure.
                   1005:  *
                   1006:  *  Parameters
                   1007:  *\li  f_key   Key structure to be freed.
                   1008:  */
                   1009:
                   1010: DST_KEY *
                   1011: dst_free_key(DST_KEY *f_key)
                   1012: {
                   1013:
                   1014:        if (f_key == NULL)
                   1015:                return (f_key);
                   1016:        if (f_key->dk_func && f_key->dk_func->destroy)
                   1017:                f_key->dk_KEY_struct =
                   1018:                        f_key->dk_func->destroy(f_key->dk_KEY_struct);
                   1019:        else {
                   1020:                EREPORT(("%s: Unknown key alg %d\n", __func__, f_key->dk_alg));
                   1021:        }
                   1022:        if (f_key->dk_KEY_struct) {
                   1023:                free(f_key->dk_KEY_struct);
                   1024:                f_key->dk_KEY_struct = NULL;
                   1025:        }
                   1026:        if (f_key->dk_key_name)
                   1027:                SAFE_FREE(f_key->dk_key_name);
                   1028:        SAFE_FREE(f_key);
                   1029:        return (NULL);
                   1030: }
                   1031:
                   1032: /*%
                   1033:  *     Return the maximim size of signature from the key specified in bytes
                   1034:  *
                   1035:  * Parameters
                   1036:  *\li      key
                   1037:  *
                   1038:  * Returns
                   1039:  *  \li   bytes
                   1040:  */
                   1041: int
                   1042: dst_sig_size(DST_KEY *key) {
                   1043:        switch (key->dk_alg) {
                   1044:            case KEY_HMAC_MD5:
                   1045:                return (16);
                   1046:            case KEY_HMAC_SHA1:
                   1047:                return (20);
                   1048:            case KEY_RSA:
                   1049:                return (key->dk_key_size + 7) / 8;
                   1050:            case KEY_DSA:
                   1051:                return (40);
                   1052:            default:
                   1053:                EREPORT(("%s: Unknown key alg %d\n", __func__, key->dk_alg));
                   1054:                return -1;
                   1055:        }
                   1056: }
                   1057:
                   1058: /*! \file */

CVSweb <webmaster@jp.NetBSD.org>