Annotation of embedaddon/dhcp/dst/dst_api.c, revision 1.1.1.1

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

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