00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <stdio.h>
00021 #include <stdlib.h>
00022 #include <unistd.h>
00023 #include <string.h>
00024 #include <ctype.h>
00025 #include <fcntl.h>
00026 #include <openssl/bn.h>
00027 #include <openssl/rsa.h>
00028 #include <openssl/evp.h>
00029 #include <openssl/x509v3.h>
00030 #include <openssl/pkcs12.h>
00031 #include <openssl/sha.h>
00032 #include <openssl/rand.h>
00033
00034 #include <ccn/keystore.h>
00035
00036 struct ccn_keystore {
00037 int initialized;
00038 EVP_PKEY *private_key;
00039 EVP_PKEY *public_key;
00040 X509 *certificate;
00041 ssize_t pubkey_digest_length;
00042 unsigned char pubkey_digest[SHA256_DIGEST_LENGTH];
00043 };
00044
00045 struct ccn_keystore *
00046 ccn_keystore_create(void)
00047 {
00048 struct ccn_keystore *res = calloc(1, sizeof(*res));
00049 return (res);
00050 }
00051
00052 void
00053 ccn_keystore_destroy(struct ccn_keystore **p)
00054 {
00055 if (*p != NULL) {
00056 if ((*p)->private_key != NULL)
00057 EVP_PKEY_free((*p)->private_key);
00058 if ((*p)->public_key != NULL)
00059 EVP_PKEY_free((*p)->public_key);
00060 if ((*p)->certificate != NULL)
00061 X509_free((*p)->certificate);
00062 free(*p);
00063 *p = NULL;
00064 }
00065 }
00066
00067 int
00068 ccn_keystore_init(struct ccn_keystore *p, char *filename, char *password)
00069 {
00070 FILE *fp;
00071 PKCS12 *keystore;
00072 int res;
00073
00074 OpenSSL_add_all_algorithms();
00075 fp = fopen(filename, "rb");
00076 if (fp == NULL)
00077 return (-1);
00078
00079 keystore = d2i_PKCS12_fp(fp, NULL);
00080 fclose(fp);
00081 if (keystore == NULL)
00082 return (-1);
00083
00084 res = PKCS12_parse(keystore, password, &(p->private_key), &(p->certificate), NULL);
00085 PKCS12_free(keystore);
00086 if (res == 0) {
00087 return (-1);
00088 }
00089 p->public_key = X509_get_pubkey(p->certificate);
00090
00091 if (1 != ASN1_item_digest(ASN1_ITEM_rptr(X509_PUBKEY), EVP_sha256(),
00092 X509_get_X509_PUBKEY(p->certificate),
00093 p->pubkey_digest, NULL)) return (-1);
00094 p->pubkey_digest_length = SHA256_DIGEST_LENGTH;
00095 p->initialized = 1;
00096 return (0);
00097 }
00098
00099 const struct ccn_pkey *
00100 ccn_keystore_private_key(struct ccn_keystore *p)
00101 {
00102 if (0 == p->initialized)
00103 return (NULL);
00104
00105 return ((const struct ccn_pkey *)(p->private_key));
00106 }
00107
00108 const struct ccn_pkey *
00109 ccn_keystore_public_key(struct ccn_keystore *p)
00110 {
00111 if (0 == p->initialized)
00112 return (NULL);
00113
00114 return ((const struct ccn_pkey *)(p->public_key));
00115 }
00116
00117 ssize_t
00118 ccn_keystore_public_key_digest_length(struct ccn_keystore *p)
00119 {
00120 return ((0 == p->initialized) ? -1 : p->pubkey_digest_length);
00121 }
00122
00123 const unsigned char *
00124 ccn_keystore_public_key_digest(struct ccn_keystore *p)
00125 {
00126 if (0 == p->initialized)
00127 return (NULL);
00128 return (p->pubkey_digest);
00129 }
00130
00131 const struct ccn_certificate *
00132 ccn_keystore_certificate(struct ccn_keystore *p)
00133 {
00134 if (0 == p->initialized)
00135 return (NULL);
00136
00137 return ((const void *)(p->certificate));
00138 }
00139
00140 static int
00141 add_cert_extension_with_context(X509 *cert, int nid, char *value)
00142 {
00143 X509_EXTENSION *extension;
00144 X509V3_CTX context;
00145
00146 X509V3_set_ctx_nodb(&context);
00147 X509V3_set_ctx(&context, cert, cert, NULL, NULL, 0);
00148 extension = X509V3_EXT_conf_nid(NULL, &context, nid, value);
00149 if (extension == NULL)
00150 return(0);
00151 X509_add_ext(cert, extension, -1);
00152 X509_EXTENSION_free(extension);
00153 return(1);
00154 }
00155
00156 static int
00157 add_cert_extension(X509 *cert, int nid, char *value)
00158 {
00159 X509_EXTENSION *extension;
00160 extension = X509V3_EXT_conf_nid(NULL, NULL, nid, value);
00161 if (extension == NULL)
00162 return(0);
00163 X509_add_ext(cert, extension, -1);
00164 X509_EXTENSION_free(extension);
00165 return(1);
00166 }
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177
00178 int
00179 ccn_keystore_file_init(char *filename, char *password,
00180 char *subject, int keylength, int validity_days)
00181 {
00182 RSA *rsa = RSA_new();
00183 BIGNUM *pub_exp = BN_new();
00184 EVP_PKEY *pkey = EVP_PKEY_new();
00185 X509 *cert = X509_new();
00186 X509_NAME *name = NULL;
00187 PKCS12 *pkcs12 = NULL;
00188 unsigned char spkid[SHA256_DIGEST_LENGTH];
00189 char spkid_hex[1 + 2 * SHA256_DIGEST_LENGTH];
00190 unsigned long serial = 0;
00191 unsigned char serial_bytes[sizeof(serial)];
00192 FILE *fp = NULL;
00193 int fd = -1;
00194 int res;
00195 int i;
00196 int ans = -1;
00197
00198
00199 if (rsa == NULL || pub_exp == NULL || pkey == NULL || cert == NULL)
00200 goto Bail;
00201
00202
00203 if (keylength <= 0)
00204 keylength = 1024;
00205 if (validity_days <= 0)
00206 validity_days = 30;
00207
00208 OpenSSL_add_all_algorithms();
00209
00210 BN_set_word(pub_exp, RSA_F4);
00211 res = 1;
00212 res &= RSA_generate_key_ex(rsa, keylength, pub_exp, NULL);
00213 res &= EVP_PKEY_set1_RSA(pkey, rsa);
00214 res &= X509_set_version(cert, 2);
00215 if (res == 0)
00216 goto Bail;
00217
00218
00219 RAND_bytes(serial_bytes, sizeof(serial_bytes));
00220 serial_bytes[0] &= 0x7F;
00221 serial = 0;
00222 for (i=0; i < sizeof(serial_bytes); i++) {
00223 serial = (256 * serial) + serial_bytes[i];
00224 }
00225 ASN1_INTEGER_set(X509_get_serialNumber(cert), serial);
00226
00227
00228 X509_gmtime_adj(X509_get_notBefore(cert), (long)0);
00229 X509_gmtime_adj(X509_get_notAfter(cert), (long)(60 * 60 * 24 * validity_days));
00230 X509_set_pubkey(cert, pkey);
00231
00232
00233 name = X509_get_subject_name(cert);
00234 if (name == NULL)
00235 goto Bail;
00236 res = X509_NAME_add_entry_by_txt(name, "CN", MBSTRING_ASC, (unsigned char *)subject, -1, -1, 0);
00237 res &= X509_set_issuer_name(cert, name);
00238
00239
00240 res &= add_cert_extension(cert, NID_basic_constraints, "critical,CA:FALSE");
00241 res &= add_cert_extension(cert, NID_key_usage, "digitalSignature,nonRepudiation,keyEncipherment,dataEncipherment,keyAgreement");
00242 res &= add_cert_extension(cert, NID_ext_key_usage, "clientAuth");
00243
00244 if (res == 0)
00245 goto Bail;
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255 res = ASN1_item_digest(ASN1_ITEM_rptr(X509_PUBKEY), EVP_sha256(),
00256 X509_get_X509_PUBKEY(cert),
00257 spkid, NULL);
00258
00259 for (i = 0; i < 32; i++) snprintf(&spkid_hex[2 * i], 3, "%02X", (unsigned)spkid[i]);
00260 res &= add_cert_extension(cert, NID_subject_key_identifier, spkid_hex);
00261 res &= add_cert_extension_with_context(cert, NID_authority_key_identifier, "keyid:always");
00262 if (res == 0)
00263 goto Bail;
00264
00265
00266 res = X509_sign(cert, pkey, EVP_sha1());
00267 if (res == 0)
00268 goto Bail;
00269
00270
00271 pkcs12 = PKCS12_create(password, "ccnxuser", pkey, cert, NULL, 0, 0,
00272 0 , PKCS12_DEFAULT_ITER , 0);
00273 if (pkcs12 == NULL)
00274 goto Bail;
00275
00276 fd = open(filename, O_CREAT | O_WRONLY | O_TRUNC, 0600);
00277 if (fd == -1)
00278 goto Bail;
00279 fp = fdopen(fd, "wb");
00280 if (fp == NULL)
00281 goto Bail;
00282 i2d_PKCS12_fp(fp, pkcs12);
00283 fclose(fp);
00284 fd = -1;
00285
00286 ans = 0;
00287
00288
00289
00290
00291
00292
00293
00294
00295 Bail:
00296 if (fd != -1)
00297 close(fd);
00298 if (pkey != NULL) {
00299 EVP_PKEY_free(pkey);
00300 pkey = NULL;
00301 }
00302 if (rsa != NULL) {
00303 RSA_free(rsa);
00304 rsa = NULL;
00305 }
00306 if (pub_exp != NULL){
00307 BN_free(pub_exp);
00308 pub_exp = NULL;
00309 }
00310 if (cert != NULL) {
00311 X509_free(cert);
00312 cert = NULL;
00313 }
00314 if (pkcs12 != NULL) {
00315 PKCS12_free(pkcs12);
00316 pkcs12 = NULL;
00317 }
00318 return (ans);
00319 }