/* * Same as keynote_get_key_algorithm(), only verify that this is * a private key (just look at the prefix). */ static int keynote_get_private_key_algorithm(char *key, int *encoding, int *internalencoding) { if (strncasecmp(KEYNOTE_PRIVATE_KEY_PREFIX, key, KEYNOTE_PRIVATE_KEY_PREFIX_LEN)) { *internalencoding = INTERNAL_ENC_NONE; *encoding = ENCODING_NONE; return KEYNOTE_ALGORITHM_NONE; } return keynote_get_key_algorithm(key + KEYNOTE_PRIVATE_KEY_PREFIX_LEN, encoding, internalencoding); }
/* * Decode a string to a key. Return 0 on success. */ int kn_decode_key(struct keynote_deckey *dc, char *key, int keytype) { void *kk = NULL; X509 *px509Cert; EVP_PKEY *pPublicKey; unsigned char *ptr = NULL, *decoded = NULL; int encoding, internalencoding; long len = 0; keynote_errno = 0; if (keytype == KEYNOTE_PRIVATE_KEY) dc->dec_algorithm = keynote_get_private_key_algorithm(key, &encoding, &internalencoding); else dc->dec_algorithm = keynote_get_key_algorithm(key, &encoding, &internalencoding); if (dc->dec_algorithm == KEYNOTE_ALGORITHM_NONE) { if ((dc->dec_key = strdup(key)) == NULL) { keynote_errno = ERROR_MEMORY; return -1; } return 0; } key = strchr(key, ':'); /* Move forward, to the Encoding. We're guaranteed * to have a ':' character, since this is a key */ key++; /* Remove ASCII encoding */ switch (encoding) { case ENCODING_NONE: break; case ENCODING_HEX: len = strlen(key) / 2; if (kn_decode_hex(key, (char **) &decoded) != 0) return -1; ptr = decoded; break; case ENCODING_BASE64: len = strlen(key); if (len % 4) /* Base64 encoding must be a multiple of 4 */ { keynote_errno = ERROR_SYNTAX; return -1; } len = 3 * (len / 4); decoded = calloc(len, sizeof(unsigned char)); ptr = decoded; if (decoded == NULL) { keynote_errno = ERROR_MEMORY; return -1; } if ((len = kn_decode_base64(key, decoded, len)) == -1) return -1; break; case ENCODING_NATIVE: decoded = strdup(key); if (decoded == NULL) { keynote_errno = ERROR_MEMORY; return -1; } len = strlen(key); ptr = decoded; break; default: keynote_errno = ERROR_SYNTAX; return -1; } /* DSA-HEX */ if ((dc->dec_algorithm == KEYNOTE_ALGORITHM_DSA) && (internalencoding == INTERNAL_ENC_ASN1)) { dc->dec_key = DSA_new(); if (dc->dec_key == NULL) { keynote_errno = ERROR_MEMORY; return -1; } kk = dc->dec_key; if (keytype == KEYNOTE_PRIVATE_KEY) { if (d2i_DSAPrivateKey((DSA **) &kk,(const unsigned char **) &decoded, len) == NULL) { free(ptr); DSA_free(kk); keynote_errno = ERROR_SYNTAX; /* Could be a memory error */ return -1; } } else { if (d2i_DSAPublicKey((DSA **) &kk, (const unsigned char **) &decoded, len) == NULL) { free(ptr); DSA_free(kk); keynote_errno = ERROR_SYNTAX; /* Could be a memory error */ return -1; } } free(ptr); return 0; } /* RSA-PKCS1-HEX */ if ((dc->dec_algorithm == KEYNOTE_ALGORITHM_RSA) && (internalencoding == INTERNAL_ENC_PKCS1)) { dc->dec_key = RSA_new(); if (dc->dec_key == NULL) { keynote_errno = ERROR_MEMORY; return -1; } kk = dc->dec_key; if (keytype == KEYNOTE_PRIVATE_KEY) { if (d2i_RSAPrivateKey((RSA **) &kk, (const unsigned char **) &decoded, len) == NULL) { free(ptr); RSA_free(kk); keynote_errno = ERROR_SYNTAX; /* Could be a memory error */ return -1; } if (RSA_blinding_on((RSA *) kk, NULL) != 1) { free(ptr); RSA_free(kk); keynote_errno = ERROR_MEMORY; return -1; } } else { if (d2i_RSAPublicKey((RSA **) &kk, (const unsigned char **) &decoded, len) == NULL) { free(ptr); RSA_free(kk); keynote_errno = ERROR_SYNTAX; /* Could be a memory error */ return -1; } } free(ptr); return 0; } /* X509 Cert */ if ((dc->dec_algorithm == KEYNOTE_ALGORITHM_X509) && (internalencoding == INTERNAL_ENC_ASN1) && (keytype == KEYNOTE_PUBLIC_KEY)) { if ((px509Cert = X509_new()) == NULL) { free(ptr); keynote_errno = ERROR_MEMORY; return -1; } if(d2i_X509(&px509Cert, (const unsigned char **)&decoded, len) == NULL) { free(ptr); X509_free(px509Cert); keynote_errno = ERROR_SYNTAX; return -1; } if ((pPublicKey = X509_get_pubkey(px509Cert)) == NULL) { free(ptr); X509_free(px509Cert); keynote_errno = ERROR_SYNTAX; return -1; } /* RSA-specific */ dc->dec_key = pPublicKey->pkey.rsa; free(ptr); return 0; } /* BINARY keys */ if ((dc->dec_algorithm == KEYNOTE_ALGORITHM_BINARY) && (internalencoding == INTERNAL_ENC_NONE)) { dc->dec_key = calloc(1, sizeof(struct keynote_binary)); if (dc->dec_key == NULL) { keynote_errno = ERROR_MEMORY; return -1; } ((struct keynote_binary *) dc->dec_key)->bn_key = decoded; ((struct keynote_binary *) dc->dec_key)->bn_len = len; return RESULT_TRUE; } /* Add support for more algorithms here */ free(ptr); /* This shouldn't ever be reached really */ keynote_errno = ERROR_SYNTAX; return -1; }
void keynote_keygen(int argc, char *argv[]) { int begin = KEY_PRINT_OFFSET, prlen = KEY_PRINT_LENGTH; char *foo, *privalgname, seed[SEED_LEN]; int alg, enc, ienc, len = 0, counter; struct keynote_deckey dc; unsigned long h; DSA *dsa; RSA *rsa; FILE *fp; char *algname; if ((argc != 5) && (argc != 6) && (argc != 7)) { keygenusage(); exit(0); } /* Fix algorithm name */ if (argv[1][strlen(argv[1]) - 1] != ':') { int len = strlen(argv[1]) + 2; fprintf(stderr, "Algorithm name [%s] should be terminated with a " "colon, fixing.\n", argv[1]); algname = (char *) calloc(len, sizeof(char)); if (algname == (char *) NULL) { perror("calloc()"); exit(1); } strlcpy(algname, argv[1], len); algname[strlen(algname)] = ':'; } else algname = argv[1]; if (argc > 5) { begin = atoi(argv[5]); if (begin <= -1) { fprintf(stderr, "Erroneous value for print-offset parameter.\n"); exit(1); } } if (argc > 6) { prlen = atoi(argv[6]); if (prlen <= 0) { fprintf(stderr, "Erroneous value for print-length parameter.\n"); exit(1); } } if (strlen(algname) + 2 > prlen) { fprintf(stderr, "Parameter ``print-length'' should be larger " "than the length of AlgorithmName (%lu)\n", (unsigned long) strlen(algname)); exit(1); } alg = keynote_get_key_algorithm(algname, &enc, &ienc); len = atoi(argv[2]); if (len <= 0) { fprintf(stderr, "Invalid specified keysize %d\n", len); exit(1); } if ((alg == KEYNOTE_ALGORITHM_DSA) && (ienc == INTERNAL_ENC_ASN1) && ((enc == ENCODING_HEX) || (enc == ENCODING_BASE64))) { RAND_bytes(seed, SEED_LEN); dsa = DSA_generate_parameters(len, seed, SEED_LEN, &counter, &h, NULL , NULL); if (dsa == (DSA *) NULL) { ERR_print_errors_fp(stderr); exit(1); } if (DSA_generate_key(dsa) != 1) { ERR_print_errors_fp(stderr); exit(1); } dc.dec_algorithm = KEYNOTE_ALGORITHM_DSA; dc.dec_key = (void *) dsa; foo = kn_encode_key(&dc, ienc, enc, KEYNOTE_PUBLIC_KEY); if (foo == (char *) NULL) { fprintf(stderr, "Error encoding key (errno %d)\n", keynote_errno); exit(1); } if (!strcmp(argv[3], "-")) fp = stdout; else { fp = fopen(argv[3], "w"); if (fp == (FILE *) NULL) { perror(argv[3]); exit(1); } } print_key(fp, algname, foo, begin, prlen); free(foo); if (strcmp(argv[3], "-")) fclose(fp); foo = kn_encode_key(&dc, ienc, enc, KEYNOTE_PRIVATE_KEY); if (foo == (char *) NULL) { fprintf(stderr, "Error encoding key (errno %d)\n", keynote_errno); exit(1); } if (!strcmp(argv[4], "-")) { fp = stdout; if (!strcmp(argv[3], "-")) printf("===========================\n"); } else { fp = fopen(argv[4], "w"); if (fp == (FILE *) NULL) { perror(argv[4]); exit(1); } } len = strlen(KEYNOTE_PRIVATE_KEY_PREFIX) + strlen(foo) + 1; privalgname = (char *) calloc(len, sizeof(char)); if (privalgname == (char *) NULL) { perror("calloc()"); exit(1); } snprintf(privalgname, len, "%s%s", KEYNOTE_PRIVATE_KEY_PREFIX, algname); print_key(fp, privalgname, foo, begin, prlen); free(privalgname); free(foo); if (strcmp(argv[4], "-")) fclose(fp); exit(0); } if ((alg == KEYNOTE_ALGORITHM_RSA) && (ienc == INTERNAL_ENC_PKCS1) && ((enc == ENCODING_HEX) || (enc == ENCODING_BASE64))) { rsa = RSA_generate_key(len, DEFAULT_PUBLIC, NULL, NULL); if (rsa == (RSA *) NULL) { ERR_print_errors_fp(stderr); exit(1); } dc.dec_algorithm = KEYNOTE_ALGORITHM_RSA; dc.dec_key = (void *) rsa; foo = kn_encode_key(&dc, ienc, enc, KEYNOTE_PUBLIC_KEY); if (foo == (char *) NULL) { fprintf(stderr, "Error encoding key (errno %d)\n", keynote_errno); exit(1); } if (!strcmp(argv[3], "-")) fp = stdout; else { fp = fopen(argv[3], "w"); if (fp == (FILE *) NULL) { perror(argv[3]); exit(1); } } print_key(fp, algname, foo, begin, prlen); free(foo); if (strcmp(argv[3], "-")) fclose(fp); foo = kn_encode_key(&dc, ienc, enc, KEYNOTE_PRIVATE_KEY); if (foo == (char *) NULL) { fprintf(stderr, "Error encoding key (errno %d)\n", keynote_errno); exit(1); } if (!strcmp(argv[4], "-")) { fp = stdout; if (!strcmp(argv[3], "-")) printf("===========================\n"); } else { fp = fopen(argv[4], "w"); if (fp == (FILE *) NULL) { perror(argv[4]); exit(1); } } len = strlen(KEYNOTE_PRIVATE_KEY_PREFIX) + strlen(foo) + 1; privalgname = (char *) calloc(len, sizeof(char)); if (privalgname == (char *) NULL) { perror("calloc()"); exit(1); } snprintf(privalgname, len, "%s%s", KEYNOTE_PRIVATE_KEY_PREFIX, algname); print_key(fp, privalgname, foo, begin, prlen); free(privalgname); free(foo); if (strcmp(argv[4], "-")) fclose(fp); exit(0); } /* More algorithms here */ fprintf(stderr, "Unknown/unsupported algorithm [%s]\n", algname); exit(1); }