/** * \file gen.c * * Generate a fake RSA certificate file, given as input e, d, p, q. */ #define _GNU_SOURCE #include #include #include #include #include #include #include static void usage(int ret) { static const char* help_message = "%s usage: \n" "%s pub [-n MODULUS | -p PRIME -q PRIME] -e PUBLIC_EXPONENT\n" "%s priv -p PRIME -q PRIME -e PUBLIC_EXPONENT -d PRIVATE_EXPONENT\n"; fprintf(stderr, help_message, program_invocation_short_name, program_invocation_name, program_invocation_name); exit(ret); } static int pubkey_generation(RSA* rsa) { BN_CTX *ctx = BN_CTX_new(); /* we need to get a valid public key. */ if (!(rsa->e && (rsa->n ||(rsa->p && rsa->q)))) { fprintf(stderr, "Not enough parameter for the public key generation!\n"); exit(EXIT_FAILURE); } if (!rsa->n) { rsa->n = BN_new(); BN_mul(rsa->n, rsa->p, rsa->q, ctx); } PEM_write_RSAPublicKey(stdout, rsa); BN_CTX_free(ctx); RSA_free(rsa); return EXIT_SUCCESS; } static int privkey_generation(RSA *rsa) { BIGNUM *p1, *q1; BN_CTX *ctx = BN_CTX_new(); if (!(rsa->p && rsa->q && rsa->e && rsa->d)) { fprintf(stderr, "Not enough parameter for the private key generation!\n"); return EXIT_FAILURE; } p1 = BN_new(); q1 = BN_new(); rsa->n = BN_new(); rsa->iqmp = BN_new(); rsa->dmp1 = BN_new(); rsa->dmq1 = BN_new(); /* generating RSA key */ BN_mul(rsa->n, rsa->p, rsa->q, ctx); BN_sub(p1, rsa->p, BN_value_one()); BN_sub(q1, rsa->q, BN_value_one()); BN_mod(rsa->dmq1, rsa->d, q1, ctx); BN_mod(rsa->dmp1, rsa->d, p1, ctx); BN_mod_inverse(rsa->iqmp, rsa->q, rsa->p, ctx); PEM_write_RSAPrivateKey(stdout, rsa, NULL, NULL, 0, NULL, NULL); BN_CTX_free(ctx); return EXIT_SUCCESS; } int main(int argc, char **argv) { int opt; RSA *rsa = RSA_new(); rsa->n = rsa->e = rsa->p = rsa->q = NULL; if (argc < 3) usage(EXIT_FAILURE); while ((opt = getopt(argc-1, argv+1, "d:e:N:n:p:q:")) != -1) { switch (opt) { case 'N': case 'n': if (!BN_dec2bn(&rsa->n, optarg)) usage(EXIT_FAILURE); break; case 'd': if (!BN_dec2bn(&rsa->d, optarg)) usage(EXIT_FAILURE); break; case 'e': if (!BN_dec2bn(&rsa->e, optarg)) usage(EXIT_FAILURE); break; case 'p': if (!BN_dec2bn(&rsa->p, optarg)) usage(EXIT_FAILURE); break; case 'q': if (!BN_dec2bn(&rsa->q, optarg)) usage(EXIT_FAILURE); break; default: usage(EXIT_FAILURE); } } if (!strcmp(argv[1], "pub")) return pubkey_generation(rsa); else if (!strcmp(argv[1], "priv")) return privkey_generation(rsa); else usage(EXIT_FAILURE); /* creating public key */ /* EVP_PKEY *pk; pk = EVP_PKEY_new(); EVP_PKEY_set1_RSA(pk, rsa); */ /* creating dummy certificate */ /* X509* crt; crt = X509_new(); if (!X509_set_pubkey(crt, pk)) exit(EXIT_FAILURE); */ /* PEM_write_X509(stdout, crt); */ /* X509_free(crt); EVP_PKEY_free(pk); BN_free(q1); BN_free(p1); RSA_free(rsa); */ return EXIT_SUCCESS; }