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