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

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

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