Annotation of embedaddon/ntp/util/ntp-keygen.c, revision 1.1.1.1

1.1       misho       1: /*
                      2:  * Program to generate cryptographic keys for ntp clients and servers
                      3:  *
                      4:  * This program generates password encrypted data files for use with the
                      5:  * Autokey security protocol and Network Time Protocol Version 4. Files
                      6:  * are prefixed with a header giving the name and date of creation
                      7:  * followed by a type-specific descriptive label and PEM-encoded data
                      8:  * structure compatible with programs of the OpenSSL library.
                      9:  *
                     10:  * All file names are like "ntpkey_<type>_<hostname>.<filestamp>", where
                     11:  * <type> is the file type, <hostname> the generating host name and
                     12:  * <filestamp> the generation time in NTP seconds. The NTP programs
                     13:  * expect generic names such as "ntpkey_<type>_whimsy.udel.edu" with the
                     14:  * association maintained by soft links. Following is a list of file
                     15:  * types; the first line is the file name and the second link name.
                     16:  *
                     17:  * ntpkey_MD5key_<hostname>.<filestamp>
                     18:  *     MD5 (128-bit) keys used to compute message digests in symmetric
                     19:  *     key cryptography
                     20:  *
                     21:  * ntpkey_RSAhost_<hostname>.<filestamp>
                     22:  * ntpkey_host_<hostname>
                     23:  *     RSA private/public host key pair used for public key signatures
                     24:  *
                     25:  * ntpkey_RSAsign_<hostname>.<filestamp>
                     26:  * ntpkey_sign_<hostname>
                     27:  *     RSA private/public sign key pair used for public key signatures
                     28:  *
                     29:  * ntpkey_DSAsign_<hostname>.<filestamp>
                     30:  * ntpkey_sign_<hostname>
                     31:  *     DSA Private/public sign key pair used for public key signatures
                     32:  *
                     33:  * Available digest/signature schemes
                     34:  *
                     35:  * RSA:        RSA-MD2, RSA-MD5, RSA-SHA, RSA-SHA1, RSA-MDC2, EVP-RIPEMD160
                     36:  * DSA:        DSA-SHA, DSA-SHA1
                     37:  *
                     38:  * ntpkey_XXXcert_<hostname>.<filestamp>
                     39:  * ntpkey_cert_<hostname>
                     40:  *     X509v3 certificate using RSA or DSA public keys and signatures.
                     41:  *     XXX is a code identifying the message digest and signature
                     42:  *     encryption algorithm
                     43:  *
                     44:  * Identity schemes. The key type par is used for the challenge; the key
                     45:  * type key is used for the response.
                     46:  *
                     47:  * ntpkey_IFFkey_<groupname>.<filestamp>
                     48:  * ntpkey_iffkey_<groupname>
                     49:  *     Schnorr (IFF) identity parameters and keys
                     50:  *
                     51:  * ntpkey_GQkey_<groupname>.<filestamp>,
                     52:  * ntpkey_gqkey_<groupname>
                     53:  *     Guillou-Quisquater (GQ) identity parameters and keys
                     54:  *
                     55:  * ntpkey_MVkeyX_<groupname>.<filestamp>,
                     56:  * ntpkey_mvkey_<groupname>
                     57:  *     Mu-Varadharajan (MV) identity parameters and keys
                     58:  *
                     59:  * Note: Once in a while because of some statistical fluke this program
                     60:  * fails to generate and verify some cryptographic data, as indicated by
                     61:  * exit status -1. In this case simply run the program again. If the
                     62:  * program does complete with exit code 0, the data are correct as
                     63:  * verified.
                     64:  *
                     65:  * These cryptographic routines are characterized by the prime modulus
                     66:  * size in bits. The default value of 512 bits is a compromise between
                     67:  * cryptographic strength and computing time and is ordinarily
                     68:  * considered adequate for this application. The routines have been
                     69:  * tested with sizes of 256, 512, 1024 and 2048 bits. Not all message
                     70:  * digest and signature encryption schemes work with sizes less than 512
                     71:  * bits. The computing time for sizes greater than 2048 bits is
                     72:  * prohibitive on all but the fastest processors. An UltraSPARC Blade
                     73:  * 1000 took something over nine minutes to generate and verify the
                     74:  * values with size 2048. An old SPARC IPC would take a week.
                     75:  *
                     76:  * The OpenSSL library used by this program expects a random seed file.
                     77:  * As described in the OpenSSL documentation, the file name defaults to
                     78:  * first the RANDFILE environment variable in the user's home directory
                     79:  * and then .rnd in the user's home directory.
                     80:  */
                     81: #ifdef HAVE_CONFIG_H
                     82: # include <config.h>
                     83: #endif
                     84: #include <string.h>
                     85: #include <stdio.h>
                     86: #include <stdlib.h>
                     87: #include <unistd.h>
                     88: #include <sys/stat.h>
                     89: #include <sys/time.h>
                     90: #include <sys/types.h>
                     91: #include "ntp_types.h"
                     92: #include "ntp_random.h"
                     93: #include "ntp_stdlib.h"
                     94: #include "ntp_assert.h"
                     95: 
                     96: #include "ntp_libopts.h"
                     97: #include "ntp-keygen-opts.h"
                     98: 
                     99: #ifdef OPENSSL
                    100: #include "openssl/bn.h"
                    101: #include "openssl/evp.h"
                    102: #include "openssl/err.h"
                    103: #include "openssl/rand.h"
                    104: #include "openssl/pem.h"
                    105: #include "openssl/x509v3.h"
                    106: #include <openssl/objects.h>
                    107: #endif /* OPENSSL */
                    108: #include <ssl_applink.c>
                    109: 
                    110: /*
                    111:  * Cryptodefines
                    112:  */
                    113: #define        MD5KEYS         10      /* number of keys generated of each type */
                    114: #define        MD5SIZE         20      /* maximum key size */
                    115: #define        JAN_1970        2208988800UL /* NTP seconds */
                    116: #define YEAR           ((long)60*60*24*365) /* one year in seconds */
                    117: #define MAXFILENAME    256     /* max file name length */
                    118: #define MAXHOSTNAME    256     /* max host name length */
                    119: #ifdef OPENSSL
                    120: #define        PLEN            512     /* default prime modulus size (bits) */
                    121: #define        ILEN            256     /* default identity modulus size (bits) */
                    122: #define        MVMAX           100     /* max MV parameters */
                    123: 
                    124: /*
                    125:  * Strings used in X509v3 extension fields
                    126:  */
                    127: #define KEY_USAGE              "digitalSignature,keyCertSign"
                    128: #define BASIC_CONSTRAINTS      "critical,CA:TRUE"
                    129: #define EXT_KEY_PRIVATE                "private"
                    130: #define EXT_KEY_TRUST          "trustRoot"
                    131: #endif /* OPENSSL */
                    132: 
                    133: /*
                    134:  * Prototypes
                    135:  */
                    136: FILE   *fheader        (const char *, const char *, const char *);
                    137: int    gen_md5         (char *);
                    138: #ifdef OPENSSL
                    139: EVP_PKEY *gen_rsa      (char *);
                    140: EVP_PKEY *gen_dsa      (char *);
                    141: EVP_PKEY *gen_iffkey   (char *);
                    142: EVP_PKEY *gen_gqkey    (char *);
                    143: EVP_PKEY *gen_mvkey    (char *, EVP_PKEY **);
                    144: void   gen_mvserv      (char *, EVP_PKEY **);
                    145: int    x509            (EVP_PKEY *, const EVP_MD *, char *, char *,
                    146:                            char *);
                    147: void   cb              (int, int, void *);
                    148: EVP_PKEY *genkey       (char *, char *);
                    149: EVP_PKEY *readkey      (char *, char *, u_int *, EVP_PKEY **);
                    150: void   writekey        (char *, char *, u_int *, EVP_PKEY **);
                    151: u_long asn2ntp         (ASN1_TIME *);
                    152: #endif /* OPENSSL */
                    153: 
                    154: /*
                    155:  * Program variables
                    156:  */
                    157: extern char *optarg;           /* command line argument */
                    158: char   *progname;
                    159: volatile int   debug = 0;              /* debug, not de bug */
                    160: #ifdef OPENSSL
                    161: u_int  modulus = PLEN;         /* prime modulus size (bits) */
                    162: u_int  modulus2 = ILEN;        /* identity modulus size (bits) */
                    163: #endif
                    164: int    nkeys;                  /* MV keys */
                    165: time_t epoch;                  /* Unix epoch (seconds) since 1970 */
                    166: u_int  fstamp;                 /* NTP filestamp */
                    167: char   *hostname = NULL;       /* host name (subject name) */
                    168: char   *groupname = NULL;      /* trusted host name (issuer name) */
                    169: char   filename[MAXFILENAME + 1]; /* file name */
                    170: char   *passwd1 = NULL;        /* input private key password */
                    171: char   *passwd2 = NULL;        /* output private key password */
                    172: #ifdef OPENSSL
                    173: long   d0, d1, d2, d3;         /* callback counters */
                    174: #endif /* OPENSSL */
                    175: 
                    176: #ifdef SYS_WINNT
                    177: BOOL init_randfile();
                    178: 
                    179: /*
                    180:  * Don't try to follow symbolic links
                    181:  */
                    182: int
                    183: readlink(char *link, char *file, int len)
                    184: {
                    185:        return (-1);
                    186: }
                    187: 
                    188: /*
                    189:  * Don't try to create a symbolic link for now.
                    190:  * Just move the file to the name you need.
                    191:  */
                    192: int
                    193: symlink(char *filename, char *linkname) {
                    194:        DeleteFile(linkname);
                    195:        MoveFile(filename, linkname);
                    196:        return (0);
                    197: }
                    198: void
                    199: InitWin32Sockets() {
                    200:        WORD wVersionRequested;
                    201:        WSADATA wsaData;
                    202:        wVersionRequested = MAKEWORD(2,0);
                    203:        if (WSAStartup(wVersionRequested, &wsaData))
                    204:        {
                    205:                fprintf(stderr, "No useable winsock.dll\n");
                    206:                exit(1);
                    207:        }
                    208: }
                    209: #endif /* SYS_WINNT */
                    210: 
                    211: /*
                    212:  * Main program
                    213:  */
                    214: int
                    215: main(
                    216:        int     argc,           /* command line options */
                    217:        char    **argv
                    218:        )
                    219: {
                    220:        struct timeval tv;      /* initialization vector */
                    221:        int     md5key = 0;     /* generate MD5 keys */
                    222: #ifdef OPENSSL
                    223:        X509    *cert = NULL;   /* X509 certificate */
                    224:        X509_EXTENSION *ext;    /* X509v3 extension */
                    225:        EVP_PKEY *pkey_host = NULL; /* host key */
                    226:        EVP_PKEY *pkey_sign = NULL; /* sign key */
                    227:        EVP_PKEY *pkey_iffkey = NULL; /* IFF sever keys */
                    228:        EVP_PKEY *pkey_gqkey = NULL; /* GQ server keys */
                    229:        EVP_PKEY *pkey_mvkey = NULL; /* MV trusted agen keys */
                    230:        EVP_PKEY *pkey_mvpar[MVMAX]; /* MV cleient keys */
                    231:        int     hostkey = 0;    /* generate RSA keys */
                    232:        int     iffkey = 0;     /* generate IFF keys */
                    233:        int     gqkey = 0;      /* generate GQ keys */
                    234:        int     mvkey = 0;      /* update MV keys */
                    235:        int     mvpar = 0;      /* generate MV parameters */
                    236:        char    *sign = NULL;   /* sign key */
                    237:        EVP_PKEY *pkey = NULL;  /* temp key */
                    238:        const EVP_MD *ectx;     /* EVP digest */
                    239:        char    pathbuf[MAXFILENAME + 1];
                    240:        const char *scheme = NULL; /* digest/signature scheme */
                    241:        char    *exten = NULL;  /* private extension */
                    242:        char    *grpkey = NULL; /* identity extension */
                    243:        int     nid;            /* X509 digest/signature scheme */
                    244:        FILE    *fstr = NULL;   /* file handle */
                    245: #define iffsw   HAVE_OPT(ID_KEY)
                    246: #endif /* OPENSSL */
                    247:        char    hostbuf[MAXHOSTNAME + 1];
                    248:        char    groupbuf[MAXHOSTNAME + 1];
                    249: 
                    250:        progname = argv[0];
                    251: 
                    252: #ifdef SYS_WINNT
                    253:        /* Initialize before OpenSSL checks */
                    254:        InitWin32Sockets();
                    255:        if (!init_randfile())
                    256:                fprintf(stderr, "Unable to initialize .rnd file\n");
                    257:        ssl_applink();
                    258: #endif
                    259: 
                    260: #ifdef OPENSSL
                    261:        ssl_check_version();
                    262: #endif /* OPENSSL */
                    263: 
                    264:        /*
                    265:         * Process options, initialize host name and timestamp.
                    266:         */
                    267:        gethostname(hostbuf, MAXHOSTNAME);
                    268:        hostname = hostbuf;
                    269:        gettimeofday(&tv, 0);
                    270: 
                    271:        epoch = tv.tv_sec;
                    272: 
                    273:        {
                    274:                int optct = ntpOptionProcess(&ntp_keygenOptions,
                    275:                                             argc, argv);
                    276:                argc -= optct;
                    277:                argv += optct;
                    278:        }
                    279: 
                    280: #ifdef OPENSSL
                    281:        if (SSLeay() == SSLEAY_VERSION_NUMBER)
                    282:                fprintf(stderr, "Using OpenSSL version %s\n",
                    283:                        SSLeay_version(SSLEAY_VERSION));
                    284:        else
                    285:                fprintf(stderr, "Built against OpenSSL %s, using version %s\n",
                    286:                        OPENSSL_VERSION_TEXT, SSLeay_version(SSLEAY_VERSION));
                    287: #endif /* OPENSSL */
                    288: 
                    289:        debug = DESC(DEBUG_LEVEL).optOccCt;
                    290:        if (HAVE_OPT( MD5KEY ))
                    291:                md5key++;
                    292: 
                    293: #ifdef OPENSSL
                    294:        passwd1 = hostbuf;
                    295:        if (HAVE_OPT( PVT_PASSWD ))
                    296:                passwd1 = strdup(OPT_ARG( PVT_PASSWD ));
                    297: 
                    298:        if (HAVE_OPT( GET_PVT_PASSWD ))
                    299:                passwd2 = strdup(OPT_ARG( GET_PVT_PASSWD ));
                    300: 
                    301:        if (HAVE_OPT( HOST_KEY ))
                    302:                hostkey++;
                    303: 
                    304:        if (HAVE_OPT( SIGN_KEY ))
                    305:                sign = strdup(OPT_ARG( SIGN_KEY ));
                    306: 
                    307:        if (HAVE_OPT( GQ_PARAMS ))
                    308:                gqkey++;
                    309: 
                    310:        if (HAVE_OPT( IFFKEY ))
                    311:                iffkey++;
                    312: 
                    313:        if (HAVE_OPT( MV_PARAMS )) {
                    314:                mvkey++;
                    315:                nkeys = OPT_VALUE_MV_PARAMS;
                    316:        }
                    317:        if (HAVE_OPT( MV_KEYS )) {
                    318:                mvpar++;
                    319:                nkeys = OPT_VALUE_MV_KEYS;
                    320:        }
                    321:        if (HAVE_OPT( MODULUS ))
                    322:                modulus = OPT_VALUE_MODULUS;
                    323: 
                    324:        if (HAVE_OPT( CERTIFICATE ))
                    325:                scheme = OPT_ARG( CERTIFICATE );
                    326: 
                    327:        if (HAVE_OPT( SUBJECT_NAME ))
                    328:                hostname = strdup(OPT_ARG( SUBJECT_NAME ));
                    329: 
                    330:        if (HAVE_OPT( ISSUER_NAME ))
                    331:                groupname = strdup(OPT_ARG( ISSUER_NAME ));
                    332: 
                    333:        if (HAVE_OPT( PVT_CERT ))
                    334:                exten = EXT_KEY_PRIVATE;
                    335: 
                    336:        if (HAVE_OPT( TRUSTED_CERT ))
                    337:                exten = EXT_KEY_TRUST;
                    338: 
                    339:        /*
                    340:         * Seed random number generator and grow weeds.
                    341:         */
                    342:        ERR_load_crypto_strings();
                    343:        OpenSSL_add_all_algorithms();
                    344:        if (!RAND_status()) {
                    345:                u_int   temp;
                    346: 
                    347:                if (RAND_file_name(pathbuf, MAXFILENAME) == NULL) {
                    348:                        fprintf(stderr, "RAND_file_name %s\n",
                    349:                            ERR_error_string(ERR_get_error(), NULL));
                    350:                        exit (-1);
                    351:                }
                    352:                temp = RAND_load_file(pathbuf, -1);
                    353:                if (temp == 0) {
                    354:                        fprintf(stderr,
                    355:                            "RAND_load_file %s not found or empty\n",
                    356:                            pathbuf);
                    357:                        exit (-1);
                    358:                }
                    359:                fprintf(stderr,
                    360:                    "Random seed file %s %u bytes\n", pathbuf, temp);
                    361:                RAND_add(&epoch, sizeof(epoch), 4.0);
                    362:        }
                    363: 
                    364:        /*
                    365:         * Load previous certificate if available.
                    366:         */
                    367:        sprintf(filename, "ntpkey_cert_%s", hostname);
                    368:        if ((fstr = fopen(filename, "r")) != NULL) {
                    369:                cert = PEM_read_X509(fstr, NULL, NULL, NULL);
                    370:                fclose(fstr);
                    371:        }
                    372:        if (cert != NULL) {
                    373: 
                    374:                /*
                    375:                 * Extract subject name.
                    376:                 */
                    377:                X509_NAME_oneline(X509_get_subject_name(cert), groupbuf,
                    378:                    MAXFILENAME);
                    379: 
                    380:                /*
                    381:                 * Extract digest/signature scheme.
                    382:                 */
                    383:                if (scheme == NULL) {
                    384:                        nid = OBJ_obj2nid(cert->cert_info->
                    385:                            signature->algorithm);
                    386:                        scheme = OBJ_nid2sn(nid);
                    387:                }
                    388: 
                    389:                /*
                    390:                 * If a key_usage extension field is present, determine
                    391:                 * whether this is a trusted or private certificate.
                    392:                 */
                    393:                if (exten == NULL) {
                    394:                        BIO     *bp;
                    395:                        int     i, cnt;
                    396:                        char    *ptr;
                    397: 
                    398:                        ptr = strstr(groupbuf, "CN=");
                    399:                        cnt = X509_get_ext_count(cert);
                    400:                        for (i = 0; i < cnt; i++) {
                    401:                                ext = X509_get_ext(cert, i);
                    402:                                if (OBJ_obj2nid(ext->object) ==
                    403:                                    NID_ext_key_usage) {
                    404:                                        bp = BIO_new(BIO_s_mem());
                    405:                                        X509V3_EXT_print(bp, ext, 0, 0);
                    406:                                        BIO_gets(bp, pathbuf,
                    407:                                            MAXFILENAME);
                    408:                                        BIO_free(bp);
                    409:                                        if (strcmp(pathbuf,
                    410:                                            "Trust Root") == 0)
                    411:                                                exten = EXT_KEY_TRUST;
                    412:                                        else if (strcmp(pathbuf,
                    413:                                            "Private") == 0)
                    414:                                                exten = EXT_KEY_PRIVATE;
                    415:                                        if (groupname == NULL)
                    416:                                                groupname = ptr + 3;
                    417:                                }
                    418:                        }
                    419:                }
                    420:        }
                    421:        if (scheme == NULL)
                    422:                scheme = "RSA-MD5";
                    423:        if (groupname == NULL)
                    424:                groupname = hostname;
                    425:        fprintf(stderr, "Using host %s group %s\n", hostname,
                    426:            groupname);
                    427:        if ((iffkey || gqkey || mvkey) && exten == NULL)
                    428:                fprintf(stderr,
                    429:                    "Warning: identity files may not be useful with a nontrusted certificate.\n");
                    430: #endif /* OPENSSL */
                    431: 
                    432:        /*
                    433:         * Create new unencrypted MD5 keys file if requested. If this
                    434:         * option is selected, ignore all other options.
                    435:         */
                    436:        if (md5key) {
                    437:                gen_md5("md5");
                    438:                exit (0);
                    439:        }
                    440: 
                    441: #ifdef OPENSSL
                    442:        /*
                    443:         * Create a new encrypted RSA host key file if requested;
                    444:         * otherwise, look for an existing host key file. If not found,
                    445:         * create a new encrypted RSA host key file. If that fails, go
                    446:         * no further.
                    447:         */
                    448:        if (hostkey)
                    449:                pkey_host = genkey("RSA", "host");
                    450:        if (pkey_host == NULL) {
                    451:                sprintf(filename, "ntpkey_host_%s", hostname);
                    452:                pkey_host = readkey(filename, passwd1, &fstamp, NULL);
                    453:                if (pkey_host != NULL) {
                    454:                        readlink(filename, filename, sizeof(filename));
                    455:                        fprintf(stderr, "Using host key %s\n",
                    456:                            filename);
                    457:                } else {
                    458:                        pkey_host = genkey("RSA", "host");
                    459:                }
                    460:        }
                    461:        if (pkey_host == NULL) {
                    462:                fprintf(stderr, "Generating host key fails\n");
                    463:                exit (-1);
                    464:        }
                    465: 
                    466:        /*
                    467:         * Create new encrypted RSA or DSA sign keys file if requested;
                    468:         * otherwise, look for an existing sign key file. If not found,
                    469:         * use the host key instead.
                    470:         */
                    471:        if (sign != NULL)
                    472:                pkey_sign = genkey(sign, "sign");
                    473:        if (pkey_sign == NULL) {
                    474:                sprintf(filename, "ntpkey_sign_%s", hostname);
                    475:                pkey_sign = readkey(filename, passwd1, &fstamp, NULL);
                    476:                if (pkey_sign != NULL) {
                    477:                        readlink(filename, filename, sizeof(filename));
                    478:                        fprintf(stderr, "Using sign key %s\n",
                    479:                            filename);
                    480:                } else if (pkey_host != NULL) {
                    481:                        pkey_sign = pkey_host;
                    482:                        fprintf(stderr, "Using host key as sign key\n");
                    483:                }
                    484:        }
                    485: 
                    486:        /*
                    487:         * Create new encrypted GQ server keys file if requested;
                    488:         * otherwise, look for an exisiting file. If found, fetch the
                    489:         * public key for the certificate.
                    490:         */
                    491:        if (gqkey)
                    492:                pkey_gqkey = gen_gqkey("gqkey");
                    493:        if (pkey_gqkey == NULL) {
                    494:                sprintf(filename, "ntpkey_gqkey_%s", groupname);
                    495:                pkey_gqkey = readkey(filename, passwd1, &fstamp, NULL);
                    496:                if (pkey_gqkey != NULL) {
                    497:                        readlink(filename, filename, sizeof(filename));
                    498:                        fprintf(stderr, "Using GQ parameters %s\n",
                    499:                            filename);
                    500:                }
                    501:        }
                    502:        if (pkey_gqkey != NULL)
                    503:                grpkey = BN_bn2hex(pkey_gqkey->pkey.rsa->q);
                    504: 
                    505:        /*
                    506:         * Write the nonencrypted GQ client parameters to the stdout
                    507:         * stream. The parameter file is the server key file with the
                    508:         * private key obscured.
                    509:         */
                    510:        if (pkey_gqkey != NULL && HAVE_OPT(ID_KEY)) {
                    511:                RSA     *rsa;
                    512: 
                    513:                epoch = fstamp - JAN_1970;
                    514:                sprintf(filename, "ntpkey_gqpar_%s.%u", groupname,
                    515:                    fstamp);
                    516:                fprintf(stderr, "Writing GQ parameters %s to stdout\n",
                    517:                    filename);
                    518:                fprintf(stdout, "# %s\n# %s\n", filename,
                    519:                    ctime(&epoch));
                    520:                rsa = pkey_gqkey->pkey.rsa;
                    521:                BN_copy(rsa->p, BN_value_one());
                    522:                BN_copy(rsa->q, BN_value_one());
                    523:                pkey = EVP_PKEY_new();
                    524:                EVP_PKEY_assign_RSA(pkey, rsa);
                    525:                PEM_write_PrivateKey(stdout, pkey, NULL, NULL, 0, NULL,
                    526:                    NULL);
                    527:                fclose(stdout);
                    528:                if (debug)
                    529:                        RSA_print_fp(stderr, rsa, 0);
                    530:        }
                    531: 
                    532:        /*
                    533:         * Write the encrypted GQ server keys to the stdout stream.
                    534:         */
                    535:        if (pkey_gqkey != NULL && passwd2 != NULL) {
                    536:                RSA     *rsa;
                    537: 
                    538:                sprintf(filename, "ntpkey_gqkey_%s.%u", groupname,
                    539:                    fstamp);
                    540:                fprintf(stderr, "Writing GQ keys %s to stdout\n",
                    541:                    filename);
                    542:                fprintf(stdout, "# %s\n# %s\n", filename,
                    543:                    ctime(&epoch));
                    544:                rsa = pkey_gqkey->pkey.rsa;
                    545:                pkey = EVP_PKEY_new();
                    546:                EVP_PKEY_assign_RSA(pkey, rsa);
                    547:                PEM_write_PrivateKey(stdout, pkey,
                    548:                    EVP_des_cbc(), NULL, 0, NULL, passwd2);
                    549:                fclose(stdout);
                    550:                if (debug)
                    551:                        RSA_print_fp(stderr, rsa, 0);
                    552:        }
                    553: 
                    554:        /*
                    555:         * Create new encrypted IFF server keys file if requested;
                    556:         * otherwise, look for existing file.
                    557:         */
                    558:        if (iffkey)
                    559:                pkey_iffkey = gen_iffkey("iffkey");
                    560:        if (pkey_iffkey == NULL) {
                    561:                sprintf(filename, "ntpkey_iffkey_%s", groupname);
                    562:                pkey_iffkey = readkey(filename, passwd1, &fstamp, NULL);
                    563:                if (pkey_iffkey != NULL) {
                    564:                        readlink(filename, filename, sizeof(filename));
                    565:                        fprintf(stderr, "Using IFF keys %s\n",
                    566:                            filename);
                    567:                }
                    568:        }
                    569: 
                    570:        /*
                    571:         * Write the nonencrypted IFF client parameters to the stdout
                    572:         * stream. The parameter file is the server key file with the
                    573:         * private key obscured.
                    574:         */
                    575:        if (pkey_iffkey != NULL && HAVE_OPT(ID_KEY)) {
                    576:                DSA     *dsa;
                    577: 
                    578:                epoch = fstamp - JAN_1970;
                    579:                sprintf(filename, "ntpkey_iffpar_%s.%u", groupname,
                    580:                    fstamp);
                    581:                fprintf(stderr, "Writing IFF parameters %s to stdout\n",
                    582:                    filename);
                    583:                fprintf(stdout, "# %s\n# %s\n", filename,
                    584:                    ctime(&epoch));
                    585:                dsa = pkey_iffkey->pkey.dsa;
                    586:                BN_copy(dsa->priv_key, BN_value_one());
                    587:                pkey = EVP_PKEY_new();
                    588:                EVP_PKEY_assign_DSA(pkey, dsa);
                    589:                PEM_write_PrivateKey(stdout, pkey, NULL, NULL, 0, NULL,
                    590:                    NULL);
                    591:                fclose(stdout);
                    592:                if (debug)
                    593:                        DSA_print_fp(stderr, dsa, 0);
                    594:        }
                    595: 
                    596:        /*
                    597:         * Write the encrypted IFF server keys to the stdout stream.
                    598:         */
                    599:        if (pkey_iffkey != NULL && passwd2 != NULL) {
                    600:                DSA     *dsa;
                    601: 
                    602:                epoch = fstamp - JAN_1970;
                    603:                sprintf(filename, "ntpkey_iffkey_%s.%u", groupname,
                    604:                    fstamp);
                    605:                fprintf(stderr, "Writing IFF keys %s to stdout\n",
                    606:                    filename);
                    607:                fprintf(stdout, "# %s\n# %s\n", filename,
                    608:                    ctime(&epoch));
                    609:                dsa = pkey_iffkey->pkey.dsa;
                    610:                pkey = EVP_PKEY_new();
                    611:                EVP_PKEY_assign_DSA(pkey, dsa);
                    612:                PEM_write_PrivateKey(stdout, pkey, EVP_des_cbc(), NULL,
                    613:                    0, NULL, passwd2);
                    614:                fclose(stdout);
                    615:                if (debug)
                    616:                        DSA_print_fp(stderr, dsa, 0);
                    617:        }
                    618: 
                    619:        /*
                    620:         * Create new encrypted MV trusted-authority keys file if
                    621:         * requested; otherwise, look for existing keys file.
                    622:         */
                    623:        if (mvkey)
                    624:                pkey_mvkey = gen_mvkey("mv", pkey_mvpar);
                    625:        if (pkey_mvkey == NULL) {
                    626:                sprintf(filename, "ntpkey_mvta_%s", groupname);
                    627:                pkey_mvkey = readkey(filename, passwd1, &fstamp,
                    628:                   pkey_mvpar);
                    629:                if (pkey_mvkey != NULL) {
                    630:                        readlink(filename, filename, sizeof(filename));
                    631:                        fprintf(stderr, "Using MV keys %s\n",
                    632:                            filename);
                    633:                }
                    634:        }
                    635: 
                    636:        /*
                    637:         * Write the nonencrypted MV client parameters to the stdout
                    638:         * stream. For the moment, we always use the client parameters
                    639:         * associated with client key 1.
                    640:         */
                    641:        if (pkey_mvkey != NULL && HAVE_OPT(ID_KEY)) {
                    642:                epoch = fstamp - JAN_1970;
                    643:                sprintf(filename, "ntpkey_mvpar_%s.%u", groupname,
                    644:                    fstamp);
                    645:                fprintf(stderr, "Writing MV parameters %s to stdout\n",
                    646:                    filename);
                    647:                fprintf(stdout, "# %s\n# %s\n", filename,
                    648:                    ctime(&epoch));
                    649:                pkey = pkey_mvpar[2];
                    650:                PEM_write_PrivateKey(stdout, pkey, NULL, NULL, 0, NULL,
                    651:                    NULL);
                    652:                fclose(stdout);
                    653:                if (debug)
                    654:                        DSA_print_fp(stderr, pkey->pkey.dsa, 0);
                    655:        }
                    656: 
                    657:        /*
                    658:         * Write the encrypted MV server keys to the stdout stream.
                    659:         */
                    660:        if (pkey_mvkey != NULL && passwd2 != NULL) {
                    661:                epoch = fstamp - JAN_1970;
                    662:                sprintf(filename, "ntpkey_mvkey_%s.%u", groupname,
                    663:                    fstamp);
                    664:                fprintf(stderr, "Writing MV keys %s to stdout\n",
                    665:                    filename);
                    666:                fprintf(stdout, "# %s\n# %s\n", filename,
                    667:                    ctime(&epoch));
                    668:                pkey = pkey_mvpar[1];
                    669:                PEM_write_PrivateKey(stdout, pkey, EVP_des_cbc(), NULL,
                    670:                    0, NULL, passwd2);
                    671:                fclose(stdout);
                    672:                if (debug)
                    673:                        DSA_print_fp(stderr, pkey->pkey.dsa, 0);
                    674:        }
                    675: 
                    676:        /*
                    677:         * Don't generate a certificate if no host keys or extracting
                    678:         * encrypted or nonencrypted keys to the standard output stream.
                    679:         */
                    680:        if (pkey_host == NULL || HAVE_OPT(ID_KEY) || passwd2 != NULL)
                    681:                exit (0);
                    682: 
                    683:        /*
                    684:         * Decode the digest/signature scheme. If trusted, set the
                    685:         * subject and issuer names to the group name; if not set both
                    686:         * to the host name.
                    687:         */
                    688:        ectx = EVP_get_digestbyname(scheme);
                    689:        if (ectx == NULL) {
                    690:                fprintf(stderr,
                    691:                    "Invalid digest/signature combination %s\n",
                    692:                    scheme);
                    693:                        exit (-1);
                    694:        }
                    695:        if (exten == NULL)
                    696:                x509(pkey_sign, ectx, grpkey, exten, hostname);
                    697:        else
                    698:                x509(pkey_sign, ectx, grpkey, exten, groupname);
                    699: #endif /* OPENSSL */
                    700:        exit (0);
                    701: }
                    702: 
                    703: 
                    704: /*
                    705:  * Generate semi-random MD5 keys compatible with NTPv3 and NTPv4. Also,
                    706:  * if OpenSSL is around, generate random SHA1 keys compatible with
                    707:  * symmetric key cryptography.
                    708:  */
                    709: int
                    710: gen_md5(
                    711:        char    *id             /* file name id */
                    712:        )
                    713: {
                    714:        u_char  md5key[MD5SIZE + 1];    /* MD5 key */
                    715:        FILE    *str;
                    716:        int     i, j;
                    717: #ifdef OPENSSL
                    718:        u_char  keystr[MD5SIZE];
                    719:        u_char  hexstr[2 * MD5SIZE + 1];
                    720:        u_char  hex[] = "0123456789abcdef";
                    721: #endif /* OPENSSL */
                    722: 
                    723:        str = fheader("MD5key", id, groupname);
                    724:        ntp_srandom((u_long)epoch);
                    725:        for (i = 1; i <= MD5KEYS; i++) {
                    726:                for (j = 0; j < MD5SIZE; j++) {
                    727:                        int temp;
                    728: 
                    729:                        while (1) {
                    730:                                temp = ntp_random() & 0xff;
                    731:                                if (temp == '#')
                    732:                                        continue;
                    733: 
                    734:                                if (temp > 0x20 && temp < 0x7f)
                    735:                                        break;
                    736:                        }
                    737:                        md5key[j] = (u_char)temp;
                    738:                }
                    739:                md5key[j] = '\0';
                    740:                fprintf(str, "%2d MD5 %s  # MD5 key\n", i,
                    741:                    md5key);
                    742:        }
                    743: #ifdef OPENSSL
                    744:        for (i = 1; i <= MD5KEYS; i++) {
                    745:                RAND_bytes(keystr, 20);
                    746:                for (j = 0; j < MD5SIZE; j++) {
                    747:                        hexstr[2 * j] = hex[keystr[j] >> 4];
                    748:                        hexstr[2 * j + 1] = hex[keystr[j] & 0xf];
                    749:                }
                    750:                hexstr[2 * MD5SIZE] = '\0';
                    751:                fprintf(str, "%2d SHA1 %s  # SHA1 key\n", i + MD5KEYS,
                    752:                    hexstr);
                    753:        }
                    754: #endif /* OPENSSL */
                    755:        fclose(str);
                    756:        return (1);
                    757: }
                    758: 
                    759: 
                    760: #ifdef OPENSSL
                    761: /*
                    762:  * readkey - load cryptographic parameters and keys
                    763:  *
                    764:  * This routine loads a PEM-encoded file of given name and password and
                    765:  * extracts the filestamp from the file name. It returns a pointer to
                    766:  * the first key if valid, NULL if not.
                    767:  */
                    768: EVP_PKEY *                     /* public/private key pair */
                    769: readkey(
                    770:        char    *cp,            /* file name */
                    771:        char    *passwd,        /* password */
                    772:        u_int   *estamp,        /* file stamp */
                    773:        EVP_PKEY **evpars       /* parameter list pointer */
                    774:        )
                    775: {
                    776:        FILE    *str;           /* file handle */
                    777:        EVP_PKEY *pkey = NULL;  /* public/private key */
                    778:        u_int   gstamp;         /* filestamp */
                    779:        char    linkname[MAXFILENAME]; /* filestamp buffer) */
                    780:        EVP_PKEY *parkey;
                    781:        char    *ptr;
                    782:        int     i;
                    783: 
                    784:        /*
                    785:         * Open the key file.
                    786:         */
                    787:        str = fopen(cp, "r");
                    788:        if (str == NULL)
                    789:                return (NULL);
                    790: 
                    791:        /*
                    792:         * Read the filestamp, which is contained in the first line.
                    793:         */
                    794:        if ((ptr = fgets(linkname, MAXFILENAME, str)) == NULL) {
                    795:                fprintf(stderr, "Empty key file %s\n", cp);
                    796:                fclose(str);
                    797:                return (NULL);
                    798:        }
                    799:        if ((ptr = strrchr(ptr, '.')) == NULL) {
                    800:                fprintf(stderr, "No filestamp found in %s\n", cp);
                    801:                fclose(str);
                    802:                return (NULL);
                    803:        }
                    804:        if (sscanf(++ptr, "%u", &gstamp) != 1) {
                    805:                fprintf(stderr, "Invalid filestamp found in %s\n", cp);
                    806:                fclose(str);
                    807:                return (NULL);
                    808:        }
                    809: 
                    810:        /*
                    811:         * Read and decrypt PEM-encoded private keys. The first one
                    812:         * found is returned. If others are expected, add them to the
                    813:         * parameter list.
                    814:         */
                    815:        for (i = 0; i <= MVMAX - 1;) {
                    816:                parkey = PEM_read_PrivateKey(str, NULL, NULL, passwd);
                    817:                if (evpars != NULL) {
                    818:                        evpars[i++] = parkey;
                    819:                        evpars[i] = NULL;
                    820:                }
                    821:                if (parkey == NULL)
                    822:                        break;
                    823: 
                    824:                if (pkey == NULL)
                    825:                        pkey = parkey;
                    826:                if (debug) {
                    827:                        if (parkey->type == EVP_PKEY_DSA)
                    828:                                DSA_print_fp(stderr, parkey->pkey.dsa,
                    829:                                    0);
                    830:                        else if (parkey->type == EVP_PKEY_RSA)
                    831:                                RSA_print_fp(stderr, parkey->pkey.rsa,
                    832:                                    0);
                    833:                }
                    834:        }
                    835:        fclose(str);
                    836:        if (pkey == NULL) {
                    837:                fprintf(stderr, "Corrupt file %s or wrong key %s\n%s\n",
                    838:                    cp, passwd, ERR_error_string(ERR_get_error(),
                    839:                    NULL));
                    840:                exit (-1);
                    841:        }
                    842:        *estamp = gstamp;
                    843:        return (pkey);
                    844: }
                    845: 
                    846: 
                    847: /*
                    848:  * Generate RSA public/private key pair
                    849:  */
                    850: EVP_PKEY *                     /* public/private key pair */
                    851: gen_rsa(
                    852:        char    *id             /* file name id */
                    853:        )
                    854: {
                    855:        EVP_PKEY *pkey;         /* private key */
                    856:        RSA     *rsa;           /* RSA parameters and key pair */
                    857:        FILE    *str;
                    858: 
                    859:        fprintf(stderr, "Generating RSA keys (%d bits)...\n", modulus);
                    860:        rsa = RSA_generate_key(modulus, 3, cb, "RSA");
                    861:        fprintf(stderr, "\n");
                    862:        if (rsa == NULL) {
                    863:                fprintf(stderr, "RSA generate keys fails\n%s\n",
                    864:                    ERR_error_string(ERR_get_error(), NULL));
                    865:                return (NULL);
                    866:        }
                    867: 
                    868:        /*
                    869:         * For signature encryption it is not necessary that the RSA
                    870:         * parameters be strictly groomed and once in a while the
                    871:         * modulus turns out to be non-prime. Just for grins, we check
                    872:         * the primality.
                    873:         */
                    874:        if (!RSA_check_key(rsa)) {
                    875:                fprintf(stderr, "Invalid RSA key\n%s\n",
                    876:                    ERR_error_string(ERR_get_error(), NULL));
                    877:                RSA_free(rsa);
                    878:                return (NULL);
                    879:        }
                    880: 
                    881:        /*
                    882:         * Write the RSA parameters and keys as a RSA private key
                    883:         * encoded in PEM.
                    884:         */
                    885:        if (strcmp(id, "sign") == 0)
                    886:                str = fheader("RSAsign", id, hostname);
                    887:        else
                    888:                str = fheader("RSAhost", id, hostname);
                    889:        pkey = EVP_PKEY_new();
                    890:        EVP_PKEY_assign_RSA(pkey, rsa);
                    891:        PEM_write_PrivateKey(str, pkey, EVP_des_cbc(), NULL, 0, NULL,
                    892:            passwd1);
                    893:        fclose(str);
                    894:        if (debug)
                    895:                RSA_print_fp(stderr, rsa, 0);
                    896:        return (pkey);
                    897: }
                    898: 
                    899:  
                    900: /*
                    901:  * Generate DSA public/private key pair
                    902:  */
                    903: EVP_PKEY *                     /* public/private key pair */
                    904: gen_dsa(
                    905:        char    *id             /* file name id */
                    906:        )
                    907: {
                    908:        EVP_PKEY *pkey;         /* private key */
                    909:        DSA     *dsa;           /* DSA parameters */
                    910:        u_char  seed[20];       /* seed for parameters */
                    911:        FILE    *str;
                    912: 
                    913:        /*
                    914:         * Generate DSA parameters.
                    915:         */
                    916:        fprintf(stderr,
                    917:            "Generating DSA parameters (%d bits)...\n", modulus);
                    918:        RAND_bytes(seed, sizeof(seed));
                    919:        dsa = DSA_generate_parameters(modulus, seed, sizeof(seed), NULL,
                    920:            NULL, cb, "DSA");
                    921:        fprintf(stderr, "\n");
                    922:        if (dsa == NULL) {
                    923:                fprintf(stderr, "DSA generate parameters fails\n%s\n",
                    924:                    ERR_error_string(ERR_get_error(), NULL));
                    925:                return (NULL);
                    926:        }
                    927: 
                    928:        /*
                    929:         * Generate DSA keys.
                    930:         */
                    931:        fprintf(stderr, "Generating DSA keys (%d bits)...\n", modulus);
                    932:        if (!DSA_generate_key(dsa)) {
                    933:                fprintf(stderr, "DSA generate keys fails\n%s\n",
                    934:                    ERR_error_string(ERR_get_error(), NULL));
                    935:                DSA_free(dsa);
                    936:                return (NULL);
                    937:        }
                    938: 
                    939:        /*
                    940:         * Write the DSA parameters and keys as a DSA private key
                    941:         * encoded in PEM.
                    942:         */
                    943:        str = fheader("DSAsign", id, hostname);
                    944:        pkey = EVP_PKEY_new();
                    945:        EVP_PKEY_assign_DSA(pkey, dsa);
                    946:        PEM_write_PrivateKey(str, pkey, EVP_des_cbc(), NULL, 0, NULL,
                    947:            passwd1);
                    948:        fclose(str);
                    949:        if (debug)
                    950:                DSA_print_fp(stderr, dsa, 0);
                    951:        return (pkey);
                    952: }
                    953: 
                    954: 
                    955: /*
                    956:  ***********************************************************************
                    957:  *                                                                    *
                    958:  * The following routines implement the Schnorr (IFF) identity scheme  *
                    959:  *                                                                    *
                    960:  ***********************************************************************
                    961:  *
                    962:  * The Schnorr (IFF) identity scheme is intended for use when
                    963:  * certificates are generated by some other trusted certificate
                    964:  * authority and the certificate cannot be used to convey public
                    965:  * parameters. There are two kinds of files: encrypted server files that
                    966:  * contain private and public values and nonencrypted client files that
                    967:  * contain only public values. New generations of server files must be
                    968:  * securely transmitted to all servers of the group; client files can be
                    969:  * distributed by any means. The scheme is self contained and
                    970:  * independent of new generations of host keys, sign keys and
                    971:  * certificates.
                    972:  *
                    973:  * The IFF values hide in a DSA cuckoo structure which uses the same
                    974:  * parameters. The values are used by an identity scheme based on DSA
                    975:  * cryptography and described in Stimson p. 285. The p is a 512-bit
                    976:  * prime, g a generator of Zp* and q a 160-bit prime that divides p - 1
                    977:  * and is a qth root of 1 mod p; that is, g^q = 1 mod p. The TA rolls a
                    978:  * private random group key b (0 < b < q) and public key v = g^b, then
                    979:  * sends (p, q, g, b) to the servers and (p, q, g, v) to the clients.
                    980:  * Alice challenges Bob to confirm identity using the protocol described
                    981:  * below.
                    982:  *
                    983:  * How it works
                    984:  *
                    985:  * The scheme goes like this. Both Alice and Bob have the public primes
                    986:  * p, q and generator g. The TA gives private key b to Bob and public
                    987:  * key v to Alice.
                    988:  *
                    989:  * Alice rolls new random challenge r (o < r < q) and sends to Bob in
                    990:  * the IFF request message. Bob rolls new random k (0 < k < q), then
                    991:  * computes y = k + b r mod q and x = g^k mod p and sends (y, hash(x))
                    992:  * to Alice in the response message. Besides making the response
                    993:  * shorter, the hash makes it effectivey impossible for an intruder to
                    994:  * solve for b by observing a number of these messages.
                    995:  * 
                    996:  * Alice receives the response and computes g^y v^r mod p. After a bit
                    997:  * of algebra, this simplifies to g^k. If the hash of this result
                    998:  * matches hash(x), Alice knows that Bob has the group key b. The signed
                    999:  * response binds this knowledge to Bob's private key and the public key
                   1000:  * previously received in his certificate.
                   1001:  */
                   1002: /*
                   1003:  * Generate Schnorr (IFF) keys.
                   1004:  */
                   1005: EVP_PKEY *                     /* DSA cuckoo nest */
                   1006: gen_iffkey(
                   1007:        char    *id             /* file name id */
                   1008:        )
                   1009: {
                   1010:        EVP_PKEY *pkey;         /* private key */
                   1011:        DSA     *dsa;           /* DSA parameters */
                   1012:        u_char  seed[20];       /* seed for parameters */
                   1013:        BN_CTX  *ctx;           /* BN working space */
                   1014:        BIGNUM  *b, *r, *k, *u, *v, *w; /* BN temp */
                   1015:        FILE    *str;
                   1016:        u_int   temp;
                   1017: 
                   1018:        /*
                   1019:         * Generate DSA parameters for use as IFF parameters.
                   1020:         */
                   1021:        fprintf(stderr, "Generating IFF keys (%d bits)...\n",
                   1022:            modulus2);
                   1023:        RAND_bytes(seed, sizeof(seed));
                   1024:        dsa = DSA_generate_parameters(modulus2, seed, sizeof(seed), NULL,
                   1025:            NULL, cb, "IFF");
                   1026:        fprintf(stderr, "\n");
                   1027:        if (dsa == NULL) {
                   1028:                fprintf(stderr, "DSA generate parameters fails\n%s\n",
                   1029:                    ERR_error_string(ERR_get_error(), NULL));
                   1030:                return (NULL);;
                   1031:        }
                   1032: 
                   1033:        /*
                   1034:         * Generate the private and public keys. The DSA parameters and
                   1035:         * private key are distributed to the servers, while all except
                   1036:         * the private key are distributed to the clients.
                   1037:         */
                   1038:        b = BN_new(); r = BN_new(); k = BN_new();
                   1039:        u = BN_new(); v = BN_new(); w = BN_new(); ctx = BN_CTX_new();
                   1040:        BN_rand(b, BN_num_bits(dsa->q), -1, 0); /* a */
                   1041:        BN_mod(b, b, dsa->q, ctx);
                   1042:        BN_sub(v, dsa->q, b);
                   1043:        BN_mod_exp(v, dsa->g, v, dsa->p, ctx); /* g^(q - b) mod p */
                   1044:        BN_mod_exp(u, dsa->g, b, dsa->p, ctx);  /* g^b mod p */
                   1045:        BN_mod_mul(u, u, v, dsa->p, ctx);
                   1046:        temp = BN_is_one(u);
                   1047:        fprintf(stderr,
                   1048:            "Confirm g^(q - b) g^b = 1 mod p: %s\n", temp == 1 ?
                   1049:            "yes" : "no");
                   1050:        if (!temp) {
                   1051:                BN_free(b); BN_free(r); BN_free(k);
                   1052:                BN_free(u); BN_free(v); BN_free(w); BN_CTX_free(ctx);
                   1053:                return (NULL);
                   1054:        }
                   1055:        dsa->priv_key = BN_dup(b);              /* private key */
                   1056:        dsa->pub_key = BN_dup(v);               /* public key */
                   1057: 
                   1058:        /*
                   1059:         * Here is a trial round of the protocol. First, Alice rolls
                   1060:         * random nonce r mod q and sends it to Bob. She needs only
                   1061:         * q from parameters.
                   1062:         */
                   1063:        BN_rand(r, BN_num_bits(dsa->q), -1, 0); /* r */
                   1064:        BN_mod(r, r, dsa->q, ctx);
                   1065: 
                   1066:        /*
                   1067:         * Bob rolls random nonce k mod q, computes y = k + b r mod q
                   1068:         * and x = g^k mod p, then sends (y, x) to Alice. He needs
                   1069:         * p, q and b from parameters and r from Alice.
                   1070:         */
                   1071:        BN_rand(k, BN_num_bits(dsa->q), -1, 0); /* k, 0 < k < q  */
                   1072:        BN_mod(k, k, dsa->q, ctx);
                   1073:        BN_mod_mul(v, dsa->priv_key, r, dsa->q, ctx); /* b r mod q */
                   1074:        BN_add(v, v, k);
                   1075:        BN_mod(v, v, dsa->q, ctx);              /* y = k + b r mod q */
                   1076:        BN_mod_exp(u, dsa->g, k, dsa->p, ctx);  /* x = g^k mod p */
                   1077: 
                   1078:        /*
                   1079:         * Alice verifies x = g^y v^r to confirm that Bob has group key
                   1080:         * b. She needs p, q, g from parameters, (y, x) from Bob and the
                   1081:         * original r. We omit the detail here thatt only the hash of y
                   1082:         * is sent.
                   1083:         */
                   1084:        BN_mod_exp(v, dsa->g, v, dsa->p, ctx); /* g^y mod p */
                   1085:        BN_mod_exp(w, dsa->pub_key, r, dsa->p, ctx); /* v^r */
                   1086:        BN_mod_mul(v, w, v, dsa->p, ctx);       /* product mod p */
                   1087:        temp = BN_cmp(u, v);
                   1088:        fprintf(stderr,
                   1089:            "Confirm g^k = g^(k + b r) g^(q - b) r: %s\n", temp ==
                   1090:            0 ? "yes" : "no");
                   1091:        BN_free(b); BN_free(r); BN_free(k);
                   1092:        BN_free(u); BN_free(v); BN_free(w); BN_CTX_free(ctx);
                   1093:        if (temp != 0) {
                   1094:                DSA_free(dsa);
                   1095:                return (NULL);
                   1096:        }
                   1097: 
                   1098:        /*
                   1099:         * Write the IFF keys as an encrypted DSA private key encoded in
                   1100:         * PEM.
                   1101:         *
                   1102:         * p    modulus p
                   1103:         * q    modulus q
                   1104:         * g    generator g
                   1105:         * priv_key b
                   1106:         * public_key v
                   1107:         * kinv not used
                   1108:         * r    not used
                   1109:         */
                   1110:        str = fheader("IFFkey", id, groupname);
                   1111:        pkey = EVP_PKEY_new();
                   1112:        EVP_PKEY_assign_DSA(pkey, dsa);
                   1113:        PEM_write_PrivateKey(str, pkey, EVP_des_cbc(), NULL, 0, NULL,
                   1114:            passwd1);
                   1115:        fclose(str);
                   1116:        if (debug)
                   1117:                DSA_print_fp(stderr, dsa, 0);
                   1118:        return (pkey);
                   1119: }
                   1120: 
                   1121: 
                   1122: /*
                   1123:  ***********************************************************************
                   1124:  *                                                                    *
                   1125:  * The following routines implement the Guillou-Quisquater (GQ)        *
                   1126:  * identity scheme                                                     *
                   1127:  *                                                                    *
                   1128:  ***********************************************************************
                   1129:  *
                   1130:  * The Guillou-Quisquater (GQ) identity scheme is intended for use when
                   1131:  * the certificate can be used to convey public parameters. The scheme
                   1132:  * uses a X509v3 certificate extension field do convey the public key of
                   1133:  * a private key known only to servers. There are two kinds of files:
                   1134:  * encrypted server files that contain private and public values and
                   1135:  * nonencrypted client files that contain only public values. New
                   1136:  * generations of server files must be securely transmitted to all
                   1137:  * servers of the group; client files can be distributed by any means.
                   1138:  * The scheme is self contained and independent of new generations of
                   1139:  * host keys and sign keys. The scheme is self contained and independent
                   1140:  * of new generations of host keys and sign keys.
                   1141:  *
                   1142:  * The GQ parameters hide in a RSA cuckoo structure which uses the same
                   1143:  * parameters. The values are used by an identity scheme based on RSA
                   1144:  * cryptography and described in Stimson p. 300 (with errors). The 512-
                   1145:  * bit public modulus is n = p q, where p and q are secret large primes.
                   1146:  * The TA rolls private random group key b as RSA exponent. These values
                   1147:  * are known to all group members.
                   1148:  *
                   1149:  * When rolling new certificates, a server recomputes the private and
                   1150:  * public keys. The private key u is a random roll, while the public key
                   1151:  * is the inverse obscured by the group key v = (u^-1)^b. These values
                   1152:  * replace the private and public keys normally generated by the RSA
                   1153:  * scheme. Alice challenges Bob to confirm identity using the protocol
                   1154:  * described below.
                   1155:  *
                   1156:  * How it works
                   1157:  *
                   1158:  * The scheme goes like this. Both Alice and Bob have the same modulus n
                   1159:  * and some random b as the group key. These values are computed and
                   1160:  * distributed in advance via secret means, although only the group key
                   1161:  * b is truly secret. Each has a private random private key u and public
                   1162:  * key (u^-1)^b, although not necessarily the same ones. Bob and Alice
                   1163:  * can regenerate the key pair from time to time without affecting
                   1164:  * operations. The public key is conveyed on the certificate in an
                   1165:  * extension field; the private key is never revealed.
                   1166:  *
                   1167:  * Alice rolls new random challenge r and sends to Bob in the GQ
                   1168:  * request message. Bob rolls new random k, then computes y = k u^r mod
                   1169:  * n and x = k^b mod n and sends (y, hash(x)) to Alice in the response
                   1170:  * message. Besides making the response shorter, the hash makes it
                   1171:  * effectivey impossible for an intruder to solve for b by observing
                   1172:  * a number of these messages.
                   1173:  * 
                   1174:  * Alice receives the response and computes y^b v^r mod n. After a bit
                   1175:  * of algebra, this simplifies to k^b. If the hash of this result
                   1176:  * matches hash(x), Alice knows that Bob has the group key b. The signed
                   1177:  * response binds this knowledge to Bob's private key and the public key
                   1178:  * previously received in his certificate.
                   1179:  */
                   1180: /*
                   1181:  * Generate Guillou-Quisquater (GQ) parameters file.
                   1182:  */
                   1183: EVP_PKEY *                     /* RSA cuckoo nest */
                   1184: gen_gqkey(
                   1185:        char    *id             /* file name id */
                   1186:        )
                   1187: {
                   1188:        EVP_PKEY *pkey;         /* private key */
                   1189:        RSA     *rsa;           /* RSA parameters */
                   1190:        BN_CTX  *ctx;           /* BN working space */
                   1191:        BIGNUM  *u, *v, *g, *k, *r, *y; /* BN temps */
                   1192:        FILE    *str;
                   1193:        u_int   temp;
                   1194: 
                   1195:        /*
                   1196:         * Generate RSA parameters for use as GQ parameters.
                   1197:         */
                   1198:        fprintf(stderr,
                   1199:            "Generating GQ parameters (%d bits)...\n",
                   1200:             modulus2);
                   1201:        rsa = RSA_generate_key(modulus2, 3, cb, "GQ");
                   1202:        fprintf(stderr, "\n");
                   1203:        if (rsa == NULL) {
                   1204:                fprintf(stderr, "RSA generate keys fails\n%s\n",
                   1205:                    ERR_error_string(ERR_get_error(), NULL));
                   1206:                return (NULL);
                   1207:        }
                   1208:        ctx = BN_CTX_new(); u = BN_new(); v = BN_new();
                   1209:        g = BN_new(); k = BN_new(); r = BN_new(); y = BN_new();
                   1210: 
                   1211:        /*
                   1212:         * Generate the group key b, which is saved in the e member of
                   1213:         * the RSA structure. The group key is transmitted to each group
                   1214:         * member encrypted by the member private key.
                   1215:         */
                   1216:        ctx = BN_CTX_new();
                   1217:        BN_rand(rsa->e, BN_num_bits(rsa->n), -1, 0); /* b */
                   1218:        BN_mod(rsa->e, rsa->e, rsa->n, ctx);
                   1219: 
                   1220:        /*
                   1221:         * When generating his certificate, Bob rolls random private key
                   1222:         * u, then computes inverse v = u^-1. 
                   1223:         */
                   1224:        BN_rand(u, BN_num_bits(rsa->n), -1, 0); /* u */
                   1225:        BN_mod(u, u, rsa->n, ctx);
                   1226:        BN_mod_inverse(v, u, rsa->n, ctx);      /* u^-1 mod n */
                   1227:        BN_mod_mul(k, v, u, rsa->n, ctx);
                   1228: 
                   1229:        /*
                   1230:         * Bob computes public key v = (u^-1)^b, which is saved in an
                   1231:         * extension field on his certificate. We check that u^b v =
                   1232:         * 1 mod n.
                   1233:         */
                   1234:        BN_mod_exp(v, v, rsa->e, rsa->n, ctx);
                   1235:        BN_mod_exp(g, u, rsa->e, rsa->n, ctx); /* u^b */
                   1236:        BN_mod_mul(g, g, v, rsa->n, ctx); /* u^b (u^-1)^b */
                   1237:        temp = BN_is_one(g);
                   1238:        fprintf(stderr,
                   1239:            "Confirm u^b (u^-1)^b = 1 mod n: %s\n", temp ? "yes" :
                   1240:            "no");
                   1241:        if (!temp) {
                   1242:                BN_free(u); BN_free(v);
                   1243:                BN_free(g); BN_free(k); BN_free(r); BN_free(y);
                   1244:                BN_CTX_free(ctx);
                   1245:                RSA_free(rsa);
                   1246:                return (NULL);
                   1247:        }
                   1248:        BN_copy(rsa->p, u);                     /* private key */
                   1249:        BN_copy(rsa->q, v);                     /* public key */
                   1250: 
                   1251:        /*
                   1252:         * Here is a trial run of the protocol. First, Alice rolls
                   1253:         * random nonce r mod n and sends it to Bob. She needs only n
                   1254:         * from parameters.
                   1255:         */
                   1256:        BN_rand(r, BN_num_bits(rsa->n), -1, 0); /* r */
                   1257:        BN_mod(r, r, rsa->n, ctx);
                   1258: 
                   1259:        /*
                   1260:         * Bob rolls random nonce k mod n, computes y = k u^r mod n and
                   1261:         * g = k^b mod n, then sends (y, g) to Alice. He needs n, u, b
                   1262:         * from parameters and r from Alice. 
                   1263:         */
                   1264:        BN_rand(k, BN_num_bits(rsa->n), -1, 0); /* k */
                   1265:        BN_mod(k, k, rsa->n, ctx);
                   1266:        BN_mod_exp(y, rsa->p, r, rsa->n, ctx);  /* u^r mod n */
                   1267:        BN_mod_mul(y, k, y, rsa->n, ctx);       /* y = k u^r mod n */
                   1268:        BN_mod_exp(g, k, rsa->e, rsa->n, ctx);  /* g = k^b mod n */
                   1269: 
                   1270:        /*
                   1271:         * Alice verifies g = v^r y^b mod n to confirm that Bob has
                   1272:         * private key u. She needs n, g from parameters, public key v =
                   1273:         * (u^-1)^b from the certificate, (y, g) from Bob and the
                   1274:         * original r. We omit the detaul here that only the hash of g
                   1275:         * is sent.
                   1276:         */
                   1277:        BN_mod_exp(v, rsa->q, r, rsa->n, ctx);  /* v^r mod n */
                   1278:        BN_mod_exp(y, y, rsa->e, rsa->n, ctx); /* y^b mod n */
                   1279:        BN_mod_mul(y, v, y, rsa->n, ctx);       /* v^r y^b mod n */
                   1280:        temp = BN_cmp(y, g);
                   1281:        fprintf(stderr, "Confirm g^k = v^r y^b mod n: %s\n", temp == 0 ?
                   1282:            "yes" : "no");
                   1283:        BN_CTX_free(ctx); BN_free(u); BN_free(v);
                   1284:        BN_free(g); BN_free(k); BN_free(r); BN_free(y);
                   1285:        if (temp != 0) {
                   1286:                RSA_free(rsa);
                   1287:                return (NULL);
                   1288:        }
                   1289: 
                   1290:        /*
                   1291:         * Write the GQ parameter file as an encrypted RSA private key
                   1292:         * encoded in PEM.
                   1293:         *
                   1294:         * n    modulus n
                   1295:         * e    group key b
                   1296:         * d    not used
                   1297:         * p    private key u
                   1298:         * q    public key (u^-1)^b
                   1299:         * dmp1 not used
                   1300:         * dmq1 not used
                   1301:         * iqmp not used
                   1302:         */
                   1303:        BN_copy(rsa->d, BN_value_one());
                   1304:        BN_copy(rsa->dmp1, BN_value_one());
                   1305:        BN_copy(rsa->dmq1, BN_value_one());
                   1306:        BN_copy(rsa->iqmp, BN_value_one());
                   1307:        str = fheader("GQkey", id, groupname);
                   1308:        pkey = EVP_PKEY_new();
                   1309:        EVP_PKEY_assign_RSA(pkey, rsa);
                   1310:        PEM_write_PrivateKey(str, pkey, EVP_des_cbc(), NULL, 0, NULL,
                   1311:            passwd1);
                   1312:        fclose(str);
                   1313:        if (debug)
                   1314:                RSA_print_fp(stderr, rsa, 0);
                   1315:        return (pkey);
                   1316: }
                   1317: 
                   1318: 
                   1319: /*
                   1320:  ***********************************************************************
                   1321:  *                                                                    *
                   1322:  * The following routines implement the Mu-Varadharajan (MV) identity  *
                   1323:  * scheme                                                              *
                   1324:  *                                                                    *
                   1325:  ***********************************************************************
                   1326:  *
                   1327:  * The Mu-Varadharajan (MV) cryptosystem was originally intended when
                   1328:  * servers broadcast messages to clients, but clients never send
                   1329:  * messages to servers. There is one encryption key for the server and a
                   1330:  * separate decryption key for each client. It operated something like a
                   1331:  * pay-per-view satellite broadcasting system where the session key is
                   1332:  * encrypted by the broadcaster and the decryption keys are held in a
                   1333:  * tamperproof set-top box.
                   1334:  *
                   1335:  * The MV parameters and private encryption key hide in a DSA cuckoo
                   1336:  * structure which uses the same parameters, but generated in a
                   1337:  * different way. The values are used in an encryption scheme similar to
                   1338:  * El Gamal cryptography and a polynomial formed from the expansion of
                   1339:  * product terms (x - x[j]), as described in Mu, Y., and V.
                   1340:  * Varadharajan: Robust and Secure Broadcasting, Proc. Indocrypt 2001,
                   1341:  * 223-231. The paper has significant errors and serious omissions.
                   1342:  *
                   1343:  * Let q be the product of n distinct primes s1[j] (j = 1...n), where
                   1344:  * each s1[j] has m significant bits. Let p be a prime p = 2 * q + 1, so
                   1345:  * that q and each s1[j] divide p - 1 and p has M = n * m + 1
                   1346:  * significant bits. Let g be a generator of Zp; that is, gcd(g, p - 1)
                   1347:  * = 1 and g^q = 1 mod p. We do modular arithmetic over Zq and then
                   1348:  * project into Zp* as exponents of g. Sometimes we have to compute an
                   1349:  * inverse b^-1 of random b in Zq, but for that purpose we require
                   1350:  * gcd(b, q) = 1. We expect M to be in the 500-bit range and n
                   1351:  * relatively small, like 30. These are the parameters of the scheme and
                   1352:  * they are expensive to compute.
                   1353:  *
                   1354:  * We set up an instance of the scheme as follows. A set of random
                   1355:  * values x[j] mod q (j = 1...n), are generated as the zeros of a
                   1356:  * polynomial of order n. The product terms (x - x[j]) are expanded to
                   1357:  * form coefficients a[i] mod q (i = 0...n) in powers of x. These are
                   1358:  * used as exponents of the generator g mod p to generate the private
                   1359:  * encryption key A. The pair (gbar, ghat) of public server keys and the
                   1360:  * pairs (xbar[j], xhat[j]) (j = 1...n) of private client keys are used
                   1361:  * to construct the decryption keys. The devil is in the details.
                   1362:  *
                   1363:  * This routine generates a private server encryption file including the
                   1364:  * private encryption key E and partial decryption keys gbar and ghat.
                   1365:  * It then generates public client decryption files including the public
                   1366:  * keys xbar[j] and xhat[j] for each client j. The partial decryption
                   1367:  * files are used to compute the inverse of E. These values are suitably
                   1368:  * blinded so secrets are not revealed.
                   1369:  *
                   1370:  * The distinguishing characteristic of this scheme is the capability to
                   1371:  * revoke keys. Included in the calculation of E, gbar and ghat is the
                   1372:  * product s = prod(s1[j]) (j = 1...n) above. If the factor s1[j] is
                   1373:  * subsequently removed from the product and E, gbar and ghat
                   1374:  * recomputed, the jth client will no longer be able to compute E^-1 and
                   1375:  * thus unable to decrypt the messageblock.
                   1376:  *
                   1377:  * How it works
                   1378:  *
                   1379:  * The scheme goes like this. Bob has the server values (p, E, q, gbar,
                   1380:  * ghat) and Alice has the client values (p, xbar, xhat).
                   1381:  *
                   1382:  * Alice rolls new random nonce r mod p and sends to Bob in the MV
                   1383:  * request message. Bob rolls random nonce k mod q, encrypts y = r E^k
                   1384:  * mod p and sends (y, gbar^k, ghat^k) to Alice.
                   1385:  * 
                   1386:  * Alice receives the response and computes the inverse (E^k)^-1 from
                   1387:  * the partial decryption keys gbar^k, ghat^k, xbar and xhat. She then
                   1388:  * decrypts y and verifies it matches the original r. The signed
                   1389:  * response binds this knowledge to Bob's private key and the public key
                   1390:  * previously received in his certificate.
                   1391:  */
                   1392: EVP_PKEY *                     /* DSA cuckoo nest */
                   1393: gen_mvkey(
                   1394:        char    *id,            /* file name id */
                   1395:        EVP_PKEY **evpars       /* parameter list pointer */
                   1396:        )
                   1397: {
                   1398:        EVP_PKEY *pkey, *pkey1; /* private keys */
                   1399:        DSA     *dsa, *dsa2, *sdsa; /* DSA parameters */
                   1400:        BN_CTX  *ctx;           /* BN working space */
                   1401:        BIGNUM  *a[MVMAX];      /* polynomial coefficient vector */
                   1402:        BIGNUM  *g[MVMAX];      /* public key vector */
                   1403:        BIGNUM  *s1[MVMAX];     /* private enabling keys */
                   1404:        BIGNUM  *x[MVMAX];      /* polynomial zeros vector */
                   1405:        BIGNUM  *xbar[MVMAX], *xhat[MVMAX]; /* private keys vector */
                   1406:        BIGNUM  *b;             /* group key */
                   1407:        BIGNUM  *b1;            /* inverse group key */
                   1408:        BIGNUM  *s;             /* enabling key */
                   1409:        BIGNUM  *biga;          /* master encryption key */
                   1410:        BIGNUM  *bige;          /* session encryption key */
                   1411:        BIGNUM  *gbar, *ghat;   /* public key */
                   1412:        BIGNUM  *u, *v, *w;     /* BN scratch */
                   1413:        int     i, j, n;
                   1414:        FILE    *str;
                   1415:        u_int   temp;
                   1416: 
                   1417:        /*
                   1418:         * Generate MV parameters.
                   1419:         *
                   1420:         * The object is to generate a multiplicative group Zp* modulo a
                   1421:         * prime p and a subset Zq mod q, where q is the product of n
                   1422:         * distinct primes s1[j] (j = 1...n) and q divides p - 1. We
                   1423:         * first generate n m-bit primes, where the product n m is in
                   1424:         * the order of 512 bits. One or more of these may have to be
                   1425:         * replaced later. As a practical matter, it is tough to find
                   1426:         * more than 31 distinct primes for 512 bits or 61 primes for
                   1427:         * 1024 bits. The latter can take several hundred iterations
                   1428:         * and several minutes on a Sun Blade 1000.
                   1429:         */
                   1430:        n = nkeys;
                   1431:        fprintf(stderr,
                   1432:            "Generating MV parameters for %d keys (%d bits)...\n", n,
                   1433:            modulus2 / n);
                   1434:        ctx = BN_CTX_new(); u = BN_new(); v = BN_new(); w = BN_new();
                   1435:        b = BN_new(); b1 = BN_new();
                   1436:        dsa = DSA_new();
                   1437:        dsa->p = BN_new(); dsa->q = BN_new(); dsa->g = BN_new();
                   1438:        dsa->priv_key = BN_new(); dsa->pub_key = BN_new();
                   1439:        temp = 0;
                   1440:        for (j = 1; j <= n; j++) {
                   1441:                s1[j] = BN_new();
                   1442:                while (1) {
                   1443:                        BN_generate_prime(s1[j], modulus2 / n, 0, NULL,
                   1444:                            NULL, NULL, NULL);
                   1445:                        for (i = 1; i < j; i++) {
                   1446:                                if (BN_cmp(s1[i], s1[j]) == 0)
                   1447:                                        break;
                   1448:                        }
                   1449:                        if (i == j)
                   1450:                                break;
                   1451:                        temp++;
                   1452:                }
                   1453:        }
                   1454:        fprintf(stderr, "Birthday keys regenerated %d\n", temp);
                   1455: 
                   1456:        /*
                   1457:         * Compute the modulus q as the product of the primes. Compute
                   1458:         * the modulus p as 2 * q + 1 and test p for primality. If p
                   1459:         * is composite, replace one of the primes with a new distinct
                   1460:         * one and try again. Note that q will hardly be a secret since
                   1461:         * we have to reveal p to servers, but not clients. However,
                   1462:         * factoring q to find the primes should be adequately hard, as
                   1463:         * this is the same problem considered hard in RSA. Question: is
                   1464:         * it as hard to find n small prime factors totalling n bits as
                   1465:         * it is to find two large prime factors totalling n bits?
                   1466:         * Remember, the bad guy doesn't know n.
                   1467:         */
                   1468:        temp = 0;
                   1469:        while (1) {
                   1470:                BN_one(dsa->q);
                   1471:                for (j = 1; j <= n; j++)
                   1472:                        BN_mul(dsa->q, dsa->q, s1[j], ctx);
                   1473:                BN_copy(dsa->p, dsa->q);
                   1474:                BN_add(dsa->p, dsa->p, dsa->p);
                   1475:                BN_add_word(dsa->p, 1);
                   1476:                if (BN_is_prime(dsa->p, BN_prime_checks, NULL, ctx,
                   1477:                    NULL))
                   1478:                        break;
                   1479: 
                   1480:                temp++;
                   1481:                j = temp % n + 1;
                   1482:                while (1) {
                   1483:                        BN_generate_prime(u, modulus2 / n, 0, 0, NULL,
                   1484:                            NULL, NULL);
                   1485:                        for (i = 1; i <= n; i++) {
                   1486:                                if (BN_cmp(u, s1[i]) == 0)
                   1487:                                        break;
                   1488:                        }
                   1489:                        if (i > n)
                   1490:                                break;
                   1491:                }
                   1492:                BN_copy(s1[j], u);
                   1493:        }
                   1494:        fprintf(stderr, "Defective keys regenerated %d\n", temp);
                   1495: 
                   1496:        /*
                   1497:         * Compute the generator g using a random roll such that
                   1498:         * gcd(g, p - 1) = 1 and g^q = 1. This is a generator of p, not
                   1499:         * q. This may take several iterations.
                   1500:         */
                   1501:        BN_copy(v, dsa->p);
                   1502:        BN_sub_word(v, 1);
                   1503:        while (1) {
                   1504:                BN_rand(dsa->g, BN_num_bits(dsa->p) - 1, 0, 0);
                   1505:                BN_mod(dsa->g, dsa->g, dsa->p, ctx);
                   1506:                BN_gcd(u, dsa->g, v, ctx);
                   1507:                if (!BN_is_one(u))
                   1508:                        continue;
                   1509: 
                   1510:                BN_mod_exp(u, dsa->g, dsa->q, dsa->p, ctx);
                   1511:                if (BN_is_one(u))
                   1512:                        break;
                   1513:        }
                   1514: 
                   1515:        /*
                   1516:         * Setup is now complete. Roll random polynomial roots x[j]
                   1517:         * (j = 1...n) for all j. While it may not be strictly
                   1518:         * necessary, Make sure each root has no factors in common with
                   1519:         * q.
                   1520:         */
                   1521:        fprintf(stderr,
                   1522:            "Generating polynomial coefficients for %d roots (%d bits)\n",
                   1523:            n, BN_num_bits(dsa->q)); 
                   1524:        for (j = 1; j <= n; j++) {
                   1525:                x[j] = BN_new();
                   1526: 
                   1527:                while (1) {
                   1528:                        BN_rand(x[j], BN_num_bits(dsa->q), 0, 0);
                   1529:                        BN_mod(x[j], x[j], dsa->q, ctx);
                   1530:                        BN_gcd(u, x[j], dsa->q, ctx);
                   1531:                        if (BN_is_one(u))
                   1532:                                break;
                   1533:                }
                   1534:        }
                   1535: 
                   1536:        /*
                   1537:         * Generate polynomial coefficients a[i] (i = 0...n) from the
                   1538:         * expansion of root products (x - x[j]) mod q for all j. The
                   1539:         * method is a present from Charlie Boncelet.
                   1540:         */
                   1541:        for (i = 0; i <= n; i++) {
                   1542:                a[i] = BN_new();
                   1543: 
                   1544:                BN_one(a[i]);
                   1545:        }
                   1546:        for (j = 1; j <= n; j++) {
                   1547:                BN_zero(w);
                   1548:                for (i = 0; i < j; i++) {
                   1549:                        BN_copy(u, dsa->q);
                   1550:                        BN_mod_mul(v, a[i], x[j], dsa->q, ctx);
                   1551:                        BN_sub(u, u, v);
                   1552:                        BN_add(u, u, w);
                   1553:                        BN_copy(w, a[i]);
                   1554:                        BN_mod(a[i], u, dsa->q, ctx);
                   1555:                }
                   1556:        }
                   1557: 
                   1558:        /*
                   1559:         * Generate g[i] = g^a[i] mod p for all i and the generator g.
                   1560:         */
                   1561:        for (i = 0; i <= n; i++) {
                   1562:                g[i] = BN_new();
                   1563: 
                   1564:                BN_mod_exp(g[i], dsa->g, a[i], dsa->p, ctx);
                   1565:        }
                   1566: 
                   1567:        /*
                   1568:         * Verify prod(g[i]^(a[i] x[j]^i)) = 1 for all i, j. Note the
                   1569:         * a[i] x[j]^i exponent is computed mod q, but the g[i] is
                   1570:         * computed mod p. also note the expression given in the paper
                   1571:         * is incorrect.
                   1572:         */
                   1573:        temp = 1;
                   1574:        for (j = 1; j <= n; j++) {
                   1575:                BN_one(u);
                   1576:                for (i = 0; i <= n; i++) {
                   1577:                        BN_set_word(v, i);
                   1578:                        BN_mod_exp(v, x[j], v, dsa->q, ctx);
                   1579:                        BN_mod_mul(v, v, a[i], dsa->q, ctx);
                   1580:                        BN_mod_exp(v, dsa->g, v, dsa->p, ctx);
                   1581:                        BN_mod_mul(u, u, v, dsa->p, ctx);
                   1582:                }
                   1583:                if (!BN_is_one(u))
                   1584:                        temp = 0;
                   1585:        }
                   1586:        fprintf(stderr,
                   1587:            "Confirm prod(g[i]^(x[j]^i)) = 1 for all i, j: %s\n", temp ?
                   1588:            "yes" : "no");
                   1589:        if (!temp) {
                   1590:                return (NULL);
                   1591:        }
                   1592: 
                   1593:        /*
                   1594:         * Make private encryption key A. Keep it around for awhile,
                   1595:         * since it is expensive to compute.
                   1596:         */
                   1597:        biga = BN_new();
                   1598: 
                   1599:        BN_one(biga);
                   1600:        for (j = 1; j <= n; j++) {
                   1601:                for (i = 0; i < n; i++) {
                   1602:                        BN_set_word(v, i);
                   1603:                        BN_mod_exp(v, x[j], v, dsa->q, ctx);
                   1604:                        BN_mod_exp(v, g[i], v, dsa->p, ctx);
                   1605:                        BN_mod_mul(biga, biga, v, dsa->p, ctx);
                   1606:                }
                   1607:        }
                   1608: 
                   1609:        /*
                   1610:         * Roll private random group key b mod q (0 < b < q), where
                   1611:         * gcd(b, q) = 1 to guarantee b^-1 exists, then compute b^-1
                   1612:         * mod q. If b is changed, the client keys must be recomputed.
                   1613:         */
                   1614:        while (1) {
                   1615:                BN_rand(b, BN_num_bits(dsa->q), 0, 0);
                   1616:                BN_mod(b, b, dsa->q, ctx);
                   1617:                BN_gcd(u, b, dsa->q, ctx);
                   1618:                if (BN_is_one(u))
                   1619:                        break;
                   1620:        }
                   1621:        BN_mod_inverse(b1, b, dsa->q, ctx);
                   1622: 
                   1623:        /*
                   1624:         * Make private client keys (xbar[j], xhat[j]) for all j. Note
                   1625:         * that the keys for the jth client do not s1[j] or the product
                   1626:         * s1[j]) (j = 1...n) which is q by construction.
                   1627:         *
                   1628:         * Compute the factor w such that w s1[j] = s1[j] for all j. The
                   1629:         * easy way to do this is to compute (q + s1[j]) / s1[j].
                   1630:         * Exercise for the student: prove the remainder is always zero.
                   1631:         */
                   1632:        for (j = 1; j <= n; j++) {
                   1633:                xbar[j] = BN_new(); xhat[j] = BN_new();
                   1634: 
                   1635:                BN_add(w, dsa->q, s1[j]);
                   1636:                BN_div(w, u, w, s1[j], ctx);
                   1637:                BN_zero(xbar[j]);
                   1638:                BN_set_word(v, n);
                   1639:                for (i = 1; i <= n; i++) {
                   1640:                        if (i == j)
                   1641:                                continue;
                   1642:                        BN_mod_exp(u, x[i], v, dsa->q, ctx);
                   1643:                        BN_add(xbar[j], xbar[j], u);
                   1644:                }
                   1645:                BN_mod_mul(xbar[j], xbar[j], b1, dsa->q, ctx);
                   1646:                BN_mod_exp(xhat[j], x[j], v, dsa->q, ctx);
                   1647:                BN_mod_mul(xhat[j], xhat[j], w, dsa->q, ctx);
                   1648:        }
                   1649: 
                   1650:        /*
                   1651:         * We revoke client j by dividing q by s1[j]. The quotient
                   1652:         * becomes the enabling key s. Note we always have to revoke
                   1653:         * one key; otherwise, the plaintext and cryptotext would be
                   1654:         * identical. For the present there are no provisions to revoke
                   1655:         * additional keys, so we sail on with only token revocations.
                   1656:         */
                   1657:        s = BN_new();
                   1658: 
                   1659:        BN_copy(s, dsa->q);
                   1660:        BN_div(s, u, s, s1[n], ctx);
                   1661: 
                   1662:        /*
                   1663:         * For each combination of clients to be revoked, make private
                   1664:         * encryption key E = A^s and partial decryption keys gbar = g^s
                   1665:         * and ghat = g^(s b), all mod p. The servers use these keys to
                   1666:         * compute the session encryption key and partial decryption
                   1667:         * keys. These values must be regenerated if the enabling key is
                   1668:         * changed.
                   1669:         */
                   1670:        bige = BN_new(); gbar = BN_new(); ghat = BN_new();
                   1671: 
                   1672:        BN_mod_exp(bige, biga, s, dsa->p, ctx);
                   1673:        BN_mod_exp(gbar, dsa->g, s, dsa->p, ctx);
                   1674:        BN_mod_mul(v, s, b, dsa->q, ctx);
                   1675:        BN_mod_exp(ghat, dsa->g, v, dsa->p, ctx);
                   1676:        
                   1677:        /*
                   1678:         * Notes: We produce the key media in three steps. The first
                   1679:         * step is to generate the system parameters p, q, g, b, A and
                   1680:         * the enabling keys s1[j]. Associated with each s1[j] are
                   1681:         * parameters xbar[j] and xhat[j]. All of these parameters are
                   1682:         * retained in a data structure protecteted by the trusted-agent
                   1683:         * password. The p, xbar[j] and xhat[j] paremeters are
                   1684:         * distributed to the j clients. When the client keys are to be
                   1685:         * activated, the enabled keys are multipied together to form
                   1686:         * the master enabling key s. This and the other parameters are
                   1687:         * used to compute the server encryption key E and the partial
                   1688:         * decryption keys gbar and ghat.
                   1689:         *
                   1690:         * In the identity exchange the client rolls random r and sends
                   1691:         * it to the server. The server rolls random k, which is used
                   1692:         * only once, then computes the session key E^k and partial
                   1693:         * decryption keys gbar^k and ghat^k. The server sends the
                   1694:         * encrypted r along with gbar^k and ghat^k to the client. The
                   1695:         * client completes the decryption and verifies it matches r.
                   1696:         */
                   1697:        /*
                   1698:         * Write the MV trusted-agent parameters and keys as a DSA
                   1699:         * private key encoded in PEM.
                   1700:         *
                   1701:         * p    modulus p
                   1702:         * q    modulus q
                   1703:         * g    generator g
                   1704:         * priv_key A mod p
                   1705:         * pub_key b mod q
                   1706:         * (remaining values are not used)
                   1707:         */
                   1708:        i = 0;
                   1709:        str = fheader("MVta", "mvta", groupname);
                   1710:        fprintf(stderr, "Generating MV trusted-authority keys\n");
                   1711:        BN_copy(dsa->priv_key, biga);
                   1712:        BN_copy(dsa->pub_key, b);
                   1713:        pkey = EVP_PKEY_new();
                   1714:        EVP_PKEY_assign_DSA(pkey, dsa);
                   1715:        PEM_write_PrivateKey(str, pkey, EVP_des_cbc(), NULL, 0, NULL,
                   1716:            passwd1);
                   1717:        evpars[i++] = pkey;
                   1718:        if (debug)
                   1719:                DSA_print_fp(stderr, dsa, 0);
                   1720: 
                   1721:        /*
                   1722:         * Append the MV server parameters and keys as a DSA key encoded
                   1723:         * in PEM.
                   1724:         *
                   1725:         * p    modulus p
                   1726:         * q    modulus q (used only when generating k)
                   1727:         * g    bige
                   1728:         * priv_key gbar
                   1729:         * pub_key ghat
                   1730:         * (remaining values are not used)
                   1731:         */
                   1732:        fprintf(stderr, "Generating MV server keys\n");
                   1733:        dsa2 = DSA_new();
                   1734:        dsa2->p = BN_dup(dsa->p);
                   1735:        dsa2->q = BN_dup(dsa->q); 
                   1736:        dsa2->g = BN_dup(bige); 
                   1737:        dsa2->priv_key = BN_dup(gbar);
                   1738:        dsa2->pub_key = BN_dup(ghat);
                   1739:        pkey1 = EVP_PKEY_new();
                   1740:        EVP_PKEY_assign_DSA(pkey1, dsa2);
                   1741:        PEM_write_PrivateKey(str, pkey1, EVP_des_cbc(), NULL, 0, NULL,
                   1742:            passwd1);
                   1743:        evpars[i++] = pkey1;
                   1744:        if (debug)
                   1745:                DSA_print_fp(stderr, dsa2, 0);
                   1746: 
                   1747:        /*
                   1748:         * Append the MV client parameters for each client j as DSA keys
                   1749:         * encoded in PEM.
                   1750:         *
                   1751:         * p    modulus p
                   1752:         * priv_key xbar[j] mod q
                   1753:         * pub_key xhat[j] mod q
                   1754:         * (remaining values are not used)
                   1755:         */
                   1756:        fprintf(stderr, "Generating %d MV client keys\n", n);
                   1757:        for (j = 1; j <= n; j++) {
                   1758:                sdsa = DSA_new();
                   1759: 
                   1760:                sdsa->p = BN_dup(dsa->p);
                   1761:                sdsa->q = BN_dup(BN_value_one()); 
                   1762:                sdsa->g = BN_dup(BN_value_one()); 
                   1763:                sdsa->priv_key = BN_dup(xbar[j]);
                   1764:                sdsa->pub_key = BN_dup(xhat[j]);
                   1765:                pkey1 = EVP_PKEY_new();
                   1766:                EVP_PKEY_set1_DSA(pkey1, sdsa);
                   1767:                PEM_write_PrivateKey(str, pkey1, EVP_des_cbc(), NULL, 0,
                   1768:                    NULL, passwd1);
                   1769:                evpars[i++] = pkey1;
                   1770:                if (debug)
                   1771:                        DSA_print_fp(stderr, sdsa, 0);
                   1772: 
                   1773:                /*
                   1774:                 * The product gbar^k)^xbar[j] (ghat^k)^xhat[j] and E
                   1775:                 * are inverses of each other. We check that the product
                   1776:                 * is one for each client except the ones that have been
                   1777:                 * revoked. 
                   1778:                 */
                   1779:                BN_mod_exp(v, dsa2->priv_key, sdsa->pub_key, dsa->p,
                   1780:                    ctx);
                   1781:                BN_mod_exp(u, dsa2->pub_key, sdsa->priv_key, dsa->p,
                   1782:                    ctx);
                   1783:                BN_mod_mul(u, u, v, dsa->p, ctx);
                   1784:                BN_mod_mul(u, u, bige, dsa->p, ctx);
                   1785:                if (!BN_is_one(u)) {
                   1786:                        fprintf(stderr, "Revoke key %d\n", j);
                   1787:                        continue;
                   1788:                }
                   1789:        }
                   1790:        evpars[i++] = NULL;
                   1791:        fclose(str);
                   1792: 
                   1793:        /*
                   1794:         * Free the countries.
                   1795:         */
                   1796:        for (i = 0; i <= n; i++) {
                   1797:                BN_free(a[i]); BN_free(g[i]);
                   1798:        }
                   1799:        for (j = 1; j <= n; j++) {
                   1800:                BN_free(x[j]); BN_free(xbar[j]); BN_free(xhat[j]);
                   1801:                BN_free(s1[j]); 
                   1802:        }
                   1803:        return (pkey);
                   1804: }
                   1805: 
                   1806: 
                   1807: /*
                   1808:  * Generate X509v3 certificate.
                   1809:  *
                   1810:  * The certificate consists of the version number, serial number,
                   1811:  * validity interval, issuer name, subject name and public key. For a
                   1812:  * self-signed certificate, the issuer name is the same as the subject
                   1813:  * name and these items are signed using the subject private key. The
                   1814:  * validity interval extends from the current time to the same time one
                   1815:  * year hence. For NTP purposes, it is convenient to use the NTP seconds
                   1816:  * of the current time as the serial number.
                   1817:  */
                   1818: int
                   1819: x509   (
                   1820:        EVP_PKEY *pkey,         /* generic signature algorithm */
                   1821:        const EVP_MD *md,       /* generic digest algorithm */
                   1822:        char    *gqpub,         /* identity extension (hex string) */
                   1823:        char    *exten,         /* private cert extension */
                   1824:        char    *name           /* subject/issuer namd */
                   1825:        )
                   1826: {
                   1827:        X509    *cert;          /* X509 certificate */
                   1828:        X509_NAME *subj;        /* distinguished (common) name */
                   1829:        X509_EXTENSION *ex;     /* X509v3 extension */
                   1830:        FILE    *str;           /* file handle */
                   1831:        ASN1_INTEGER *serial;   /* serial number */
                   1832:        const char *id;         /* digest/signature scheme name */
                   1833:        char    pathbuf[MAXFILENAME + 1];
                   1834: 
                   1835:        /*
                   1836:         * Generate X509 self-signed certificate.
                   1837:         *
                   1838:         * Set the certificate serial to the NTP seconds for grins. Set
                   1839:         * the version to 3. Set the initial validity to the current
                   1840:         * time and the finalvalidity one year hence.
                   1841:         */
                   1842:        id = OBJ_nid2sn(md->pkey_type);
                   1843:        fprintf(stderr, "Generating new certificate %s %s\n", name, id);
                   1844:        cert = X509_new();
                   1845:        X509_set_version(cert, 2L);
                   1846:        serial = ASN1_INTEGER_new();
                   1847:        ASN1_INTEGER_set(serial, (long)epoch + JAN_1970);
                   1848:        X509_set_serialNumber(cert, serial);
                   1849:        ASN1_INTEGER_free(serial);
                   1850:        X509_time_adj(X509_get_notBefore(cert), 0L, &epoch);
                   1851:        X509_time_adj(X509_get_notAfter(cert), YEAR, &epoch);
                   1852:        subj = X509_get_subject_name(cert);
                   1853:        X509_NAME_add_entry_by_txt(subj, "commonName", MBSTRING_ASC,
                   1854:            (unsigned char *) name, strlen(name), -1, 0);
                   1855:        subj = X509_get_issuer_name(cert);
                   1856:        X509_NAME_add_entry_by_txt(subj, "commonName", MBSTRING_ASC,
                   1857:            (unsigned char *) name, strlen(name), -1, 0);
                   1858:        if (!X509_set_pubkey(cert, pkey)) {
                   1859:                fprintf(stderr, "Assign key fails\n%s\n",
                   1860:                    ERR_error_string(ERR_get_error(), NULL));
                   1861:                X509_free(cert);
                   1862:                return (0);
                   1863:        }
                   1864: 
                   1865:        /*
                   1866:         * Add X509v3 extensions if present. These represent the minimum
                   1867:         * set defined in RFC3280 less the certificate_policy extension,
                   1868:         * which is seriously obfuscated in OpenSSL.
                   1869:         */
                   1870:        /*
                   1871:         * The basic_constraints extension CA:TRUE allows servers to
                   1872:         * sign client certficitates.
                   1873:         */
                   1874:        fprintf(stderr, "%s: %s\n", LN_basic_constraints,
                   1875:            BASIC_CONSTRAINTS);
                   1876:        ex = X509V3_EXT_conf_nid(NULL, NULL, NID_basic_constraints,
                   1877:            BASIC_CONSTRAINTS);
                   1878:        if (!X509_add_ext(cert, ex, -1)) {
                   1879:                fprintf(stderr, "Add extension field fails\n%s\n",
                   1880:                    ERR_error_string(ERR_get_error(), NULL));
                   1881:                return (0);
                   1882:        }
                   1883:        X509_EXTENSION_free(ex);
                   1884: 
                   1885:        /*
                   1886:         * The key_usage extension designates the purposes the key can
                   1887:         * be used for.
                   1888:         */
                   1889:        fprintf(stderr, "%s: %s\n", LN_key_usage, KEY_USAGE);
                   1890:        ex = X509V3_EXT_conf_nid(NULL, NULL, NID_key_usage, KEY_USAGE);
                   1891:        if (!X509_add_ext(cert, ex, -1)) {
                   1892:                fprintf(stderr, "Add extension field fails\n%s\n",
                   1893:                    ERR_error_string(ERR_get_error(), NULL));
                   1894:                return (0);
                   1895:        }
                   1896:        X509_EXTENSION_free(ex);
                   1897:        /*
                   1898:         * The subject_key_identifier is used for the GQ public key.
                   1899:         * This should not be controversial.
                   1900:         */
                   1901:        if (gqpub != NULL) {
                   1902:                fprintf(stderr, "%s\n", LN_subject_key_identifier);
                   1903:                ex = X509V3_EXT_conf_nid(NULL, NULL,
                   1904:                    NID_subject_key_identifier, gqpub);
                   1905:                if (!X509_add_ext(cert, ex, -1)) {
                   1906:                        fprintf(stderr,
                   1907:                            "Add extension field fails\n%s\n",
                   1908:                            ERR_error_string(ERR_get_error(), NULL));
                   1909:                        return (0);
                   1910:                }
                   1911:                X509_EXTENSION_free(ex);
                   1912:        }
                   1913: 
                   1914:        /*
                   1915:         * The extended key usage extension is used for special purpose
                   1916:         * here. The semantics probably do not conform to the designer's
                   1917:         * intent and will likely change in future.
                   1918:         * 
                   1919:         * "trustRoot" designates a root authority
                   1920:         * "private" designates a private certificate
                   1921:         */
                   1922:        if (exten != NULL) {
                   1923:                fprintf(stderr, "%s: %s\n", LN_ext_key_usage, exten);
                   1924:                ex = X509V3_EXT_conf_nid(NULL, NULL,
                   1925:                    NID_ext_key_usage, exten);
                   1926:                if (!X509_add_ext(cert, ex, -1)) {
                   1927:                        fprintf(stderr,
                   1928:                            "Add extension field fails\n%s\n",
                   1929:                            ERR_error_string(ERR_get_error(), NULL));
                   1930:                        return (0);
                   1931:                }
                   1932:                X509_EXTENSION_free(ex);
                   1933:        }
                   1934: 
                   1935:        /*
                   1936:         * Sign and verify.
                   1937:         */
                   1938:        X509_sign(cert, pkey, md);
                   1939:        if (X509_verify(cert, pkey) <= 0) {
                   1940:                fprintf(stderr, "Verify %s certificate fails\n%s\n", id,
                   1941:                    ERR_error_string(ERR_get_error(), NULL));
                   1942:                X509_free(cert);
                   1943:                return (0);
                   1944:        }
                   1945: 
                   1946:        /*
                   1947:         * Write the certificate encoded in PEM.
                   1948:         */
                   1949:        sprintf(pathbuf, "%scert", id);
                   1950:        str = fheader(pathbuf, "cert", hostname);
                   1951:        PEM_write_X509(str, cert);
                   1952:        fclose(str);
                   1953:        if (debug)
                   1954:                X509_print_fp(stderr, cert);
                   1955:        X509_free(cert);
                   1956:        return (1);
                   1957: }
                   1958: 
                   1959: #if 0  /* asn2ntp is used only with commercial certificates */
                   1960: /*
                   1961:  * asn2ntp - convert ASN1_TIME time structure to NTP time
                   1962:  */
                   1963: u_long
                   1964: asn2ntp        (
                   1965:        ASN1_TIME *asn1time     /* pointer to ASN1_TIME structure */
                   1966:        )
                   1967: {
                   1968:        char    *v;             /* pointer to ASN1_TIME string */
                   1969:        struct  tm tm;          /* time decode structure time */
                   1970: 
                   1971:        /*
                   1972:         * Extract time string YYMMDDHHMMSSZ from ASN.1 time structure.
                   1973:         * Note that the YY, MM, DD fields start with one, the HH, MM,
                   1974:         * SS fiels start with zero and the Z character should be 'Z'
                   1975:         * for UTC. Also note that years less than 50 map to years
                   1976:         * greater than 100. Dontcha love ASN.1?
                   1977:         */
                   1978:        if (asn1time->length > 13)
                   1979:                return (-1);
                   1980:        v = (char *)asn1time->data;
                   1981:        tm.tm_year = (v[0] - '0') * 10 + v[1] - '0';
                   1982:        if (tm.tm_year < 50)
                   1983:                tm.tm_year += 100;
                   1984:        tm.tm_mon = (v[2] - '0') * 10 + v[3] - '0' - 1;
                   1985:        tm.tm_mday = (v[4] - '0') * 10 + v[5] - '0';
                   1986:        tm.tm_hour = (v[6] - '0') * 10 + v[7] - '0';
                   1987:        tm.tm_min = (v[8] - '0') * 10 + v[9] - '0';
                   1988:        tm.tm_sec = (v[10] - '0') * 10 + v[11] - '0';
                   1989:        tm.tm_wday = 0;
                   1990:        tm.tm_yday = 0;
                   1991:        tm.tm_isdst = 0;
                   1992:        return (mktime(&tm) + JAN_1970);
                   1993: }
                   1994: #endif
                   1995: 
                   1996: /*
                   1997:  * Callback routine
                   1998:  */
                   1999: void
                   2000: cb     (
                   2001:        int     n1,             /* arg 1 */
                   2002:        int     n2,             /* arg 2 */
                   2003:        void    *chr            /* arg 3 */
                   2004:        )
                   2005: {
                   2006:        switch (n1) {
                   2007:        case 0:
                   2008:                d0++;
                   2009:                fprintf(stderr, "%s %d %d %lu\r", (char *)chr, n1, n2,
                   2010:                    d0);
                   2011:                break;
                   2012:        case 1:
                   2013:                d1++;
                   2014:                fprintf(stderr, "%s\t\t%d %d %lu\r", (char *)chr, n1,
                   2015:                    n2, d1);
                   2016:                break;
                   2017:        case 2:
                   2018:                d2++;
                   2019:                fprintf(stderr, "%s\t\t\t\t%d %d %lu\r", (char *)chr,
                   2020:                    n1, n2, d2);
                   2021:                break;
                   2022:        case 3:
                   2023:                d3++;
                   2024:                fprintf(stderr, "%s\t\t\t\t\t\t%d %d %lu\r",
                   2025:                    (char *)chr, n1, n2, d3);
                   2026:                break;
                   2027:        }
                   2028: }
                   2029: 
                   2030: 
                   2031: /*
                   2032:  * Generate key
                   2033:  */
                   2034: EVP_PKEY *                     /* public/private key pair */
                   2035: genkey(
                   2036:        char    *type,          /* key type (RSA or DSA) */
                   2037:        char    *id             /* file name id */
                   2038:        )
                   2039: {
                   2040:        if (type == NULL)
                   2041:                return (NULL);
                   2042:        if (strcmp(type, "RSA") == 0)
                   2043:                return (gen_rsa(id));
                   2044: 
                   2045:        else if (strcmp(type, "DSA") == 0)
                   2046:                return (gen_dsa(id));
                   2047: 
                   2048:        fprintf(stderr, "Invalid %s key type %s\n", id, type);
                   2049:        return (NULL);
                   2050: }
                   2051: #endif /* OPENSSL */
                   2052: 
                   2053: 
                   2054: /*
                   2055:  * Generate file header and link
                   2056:  */
                   2057: FILE *
                   2058: fheader        (
                   2059:        const char *file,       /* file name id */
                   2060:        const char *ulink,      /* linkname */
                   2061:        const char *owner       /* owner name */
                   2062:        )
                   2063: {
                   2064:        FILE    *str;           /* file handle */
                   2065:        char    linkname[MAXFILENAME]; /* link name */
                   2066:        int     temp;
                   2067: 
                   2068:        sprintf(filename, "ntpkey_%s_%s.%lu", file, owner, epoch +
                   2069:            JAN_1970);
                   2070:        if ((str = fopen(filename, "w")) == NULL) {
                   2071:                perror("Write");
                   2072:                exit (-1);
                   2073:        }
                   2074:        sprintf(linkname, "ntpkey_%s_%s", ulink, owner);
                   2075:        remove(linkname);
                   2076:        temp = symlink(filename, linkname);
                   2077:        if (temp < 0)
                   2078:                perror(file);
                   2079:        fprintf(stderr, "Generating new %s file and link\n", ulink);
                   2080:        fprintf(stderr, "%s->%s\n", linkname, filename);
                   2081:        fprintf(str, "# %s\n# %s\n", filename, ctime(&epoch));
                   2082:        return (str);
                   2083: }

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