00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <stddef.h>
00021 #include <stdlib.h>
00022 #include <string.h>
00023 #include <openssl/evp.h>
00024 #include <openssl/rand.h>
00025 #include <openssl/x509.h>
00026 #include <ccn/merklepathasn1.h>
00027 #include <ccn/ccn.h>
00028 #include <ccn/signing.h>
00029 #include <ccn/random.h>
00030
00031 struct ccn_sigc {
00032 EVP_MD_CTX context;
00033 const EVP_MD *digest;
00034 };
00035
00036 struct ccn_sigc *
00037 ccn_sigc_create(void)
00038 {
00039 return (calloc(1, sizeof(struct ccn_sigc)));
00040 }
00041
00042 void
00043 ccn_sigc_destroy(struct ccn_sigc **ctx)
00044 {
00045 if (*ctx) {
00046
00047 EVP_MD_CTX_cleanup(&(*ctx)->context);
00048 free(*ctx);
00049 *ctx = NULL;
00050 }
00051 }
00052
00053 int
00054 ccn_sigc_init(struct ccn_sigc *ctx, const char *digest)
00055 {
00056 EVP_MD_CTX_init(&ctx->context);
00057 if (digest == NULL) {
00058 ctx->digest = EVP_sha256();
00059 }
00060 else {
00061
00062 fprintf(stderr, "not a DigestAlgorithm I understand right now\n");
00063 return (-1);
00064 }
00065
00066 if (0 == EVP_SignInit_ex(&ctx->context, ctx->digest, NULL))
00067 return (-1);
00068 return (0);
00069 }
00070
00071 int
00072 ccn_sigc_update(struct ccn_sigc *ctx, const void *data, size_t size)
00073 {
00074 if (0 == EVP_SignUpdate(&ctx->context, (unsigned char *)data, size))
00075 return (-1);
00076 return (0);
00077 }
00078
00079 int
00080 ccn_sigc_final(struct ccn_sigc *ctx, struct ccn_signature *signature, size_t *size, const struct ccn_pkey *priv_key)
00081 {
00082 unsigned int sig_size;
00083
00084 if (0 == EVP_SignFinal(&ctx->context, (unsigned char *)signature, &sig_size, (EVP_PKEY *)priv_key))
00085 return (-1);
00086 *size = sig_size;
00087 return (0);
00088 }
00089
00090 size_t
00091 ccn_sigc_signature_max_size(struct ccn_sigc *ctx, const struct ccn_pkey *priv_key)
00092 {
00093 return (EVP_PKEY_size((EVP_PKEY *)priv_key));
00094 }
00095
00096 #define is_left(x) (0 == (x & 1))
00097 #define node_lr(x) (x & 1)
00098 #define sibling_of(x) (x ^ 1)
00099 #define parent_of(x) (x >> 1)
00100
00101 int ccn_merkle_root_hash(const unsigned char *msg, size_t size,
00102 const struct ccn_parsed_ContentObject *co,
00103 const EVP_MD *digest_type,
00104 MP_info *merkle_path_info,
00105 unsigned char *result, int result_size)
00106 {
00107 int node = ASN1_INTEGER_get(merkle_path_info->node);
00108 EVP_MD_CTX digest_context;
00109 EVP_MD_CTX *digest_contextp = &digest_context;
00110 size_t data_size;
00111 unsigned char *input_hash[2] = {NULL, NULL};
00112
00113 int hash_index = sk_ASN1_OCTET_STRING_num(merkle_path_info->hashes) - 1;
00114
00115 int res;
00116
00117 if (result_size != EVP_MD_size(digest_type))
00118 return -1;
00119
00120
00121
00122
00123
00124
00125
00126
00127
00128 EVP_MD_CTX_init(digest_contextp);
00129 EVP_DigestInit_ex(digest_contextp, digest_type, NULL);
00130 data_size = co->offset[CCN_PCO_E_Content] - co->offset[CCN_PCO_B_Name];
00131 res = EVP_DigestUpdate(digest_contextp, msg + co->offset[CCN_PCO_B_Name], data_size);
00132 res &= EVP_DigestFinal_ex(digest_contextp, result, NULL);
00133 if (res != 1)
00134 return(-1);
00135
00136
00137 while (node != 1) {
00138 input_hash[node & 1] = result;
00139 input_hash[(node & 1) ^ 1] = sk_ASN1_OCTET_STRING_value(merkle_path_info->hashes, hash_index)->data;
00140 if (sk_ASN1_OCTET_STRING_value(merkle_path_info->hashes, hash_index)->length != result_size)
00141 return (-1);
00142 hash_index -= 1;
00143 #ifdef DEBUG
00144 fprintf(stderr, "node[%d].lefthash = ", parent_of(node));
00145 for (int x = 0; x < result_size; x++) {
00146 fprintf(stderr, "%02x", input_hash[0][x]);
00147 }
00148 fprintf(stderr, "\n");
00149
00150 fprintf(stderr, "node[%d].righthash = ", parent_of(node));
00151 for (int x = 0; x < result_size; x++) {
00152 fprintf(stderr, "%02x", input_hash[1][x]);
00153 }
00154 fprintf(stderr, "\n");
00155 #endif
00156 EVP_MD_CTX_init(digest_contextp);
00157 res = EVP_DigestInit_ex(digest_contextp, digest_type, NULL);
00158 res &= EVP_DigestUpdate(digest_contextp, input_hash[0], result_size);
00159 res &= EVP_DigestUpdate(digest_contextp, input_hash[1], result_size);
00160 res &= EVP_DigestFinal_ex(digest_contextp, result, NULL);
00161 if (res != 1)
00162 return(-1);
00163 node = parent_of(node);
00164
00165 #ifdef DEBUG
00166 fprintf(stderr, "yielding node[%d] hash = ", node);
00167 for (int x = 0; x < result_size; x++) {
00168 fprintf(stderr, "%02x", result[x]);
00169 }
00170 fprintf(stderr, "\n");
00171 #endif
00172 }
00173 return (0);
00174 }
00175
00176 int ccn_verify_signature(const unsigned char *msg,
00177 size_t size,
00178 const struct ccn_parsed_ContentObject *co,
00179 const struct ccn_pkey *verification_pubkey)
00180 {
00181 EVP_MD_CTX verc;
00182 EVP_MD_CTX *ver_ctx = &verc;
00183 X509_SIG *digest_info = NULL;
00184 MP_info *merkle_path_info = NULL;
00185 unsigned char *root_hash;
00186 size_t root_hash_size;
00187
00188 int res;
00189
00190 const EVP_MD *digest;
00191 const EVP_MD *merkle_path_digest;
00192
00193 const unsigned char *signature_bits = NULL;
00194 size_t signature_bits_size = 0;
00195 const unsigned char *witness = NULL;
00196 size_t witness_size = 0;
00197 EVP_PKEY *pkey = (EVP_PKEY *)verification_pubkey;
00198 #ifdef DEBUG
00199 int x, h;
00200 #endif
00201
00202 res = ccn_ref_tagged_BLOB(CCN_DTAG_SignatureBits, msg,
00203 co->offset[CCN_PCO_B_SignatureBits],
00204 co->offset[CCN_PCO_E_SignatureBits],
00205 &signature_bits,
00206 &signature_bits_size);
00207 if (res < 0)
00208 return (-1);
00209
00210 if (co->offset[CCN_PCO_B_DigestAlgorithm] == co->offset[CCN_PCO_E_DigestAlgorithm]) {
00211 digest = EVP_sha256();
00212 }
00213 else {
00214
00215 fprintf(stderr, "not a DigestAlgorithm I understand right now\n");
00216 return (-1);
00217 }
00218
00219 EVP_MD_CTX_init(ver_ctx);
00220 res = EVP_VerifyInit_ex(ver_ctx, digest, NULL);
00221 if (!res)
00222 return (-1);
00223
00224 if (co->offset[CCN_PCO_B_Witness] != co->offset[CCN_PCO_E_Witness]) {
00225
00226
00227
00228
00229 res = ccn_ref_tagged_BLOB(CCN_DTAG_Witness, msg,
00230 co->offset[CCN_PCO_B_Witness],
00231 co->offset[CCN_PCO_E_Witness],
00232 &witness,
00233 &witness_size);
00234 if (res < 0)
00235 return (-1);
00236
00237
00238 digest_info = d2i_X509_SIG(NULL, &witness, witness_size);
00239
00240
00241
00242
00243 ASN1_OBJECT *merkle_hash_tree_oid = OBJ_txt2obj("1.2.840.113550.11.1.2.2", 1);
00244 if (0 != OBJ_cmp(digest_info->algor->algorithm, merkle_hash_tree_oid)) {
00245 fprintf(stderr, "A witness is present without an MHT OID!\n");
00246 ASN1_OBJECT_free(merkle_hash_tree_oid);
00247 return (-1);
00248 }
00249
00250 ASN1_OBJECT_free(merkle_hash_tree_oid);
00251 merkle_path_digest = EVP_sha256();
00252
00253 merkle_path_info = d2i_MP_info(NULL, (const unsigned char **)&(digest_info->digest->data), digest_info->digest->length);
00254 #ifdef DEBUG
00255 int node = ASN1_INTEGER_get(merkle_path_info->node);
00256 int hash_count = sk_ASN1_OCTET_STRING_num(merkle_path_info->hashes);
00257 ASN1_OCTET_STRING *hash;
00258 fprintf(stderr, "A witness is present with an MHT OID\n");
00259 fprintf(stderr, "This is node %d, with %d hashes\n", node, hash_count);
00260 for (h = 0; h < hash_count; h++) {
00261 hash = sk_ASN1_OCTET_STRING_value(merkle_path_info->hashes, h);
00262 fprintf(stderr, " hashes[%d] len = %d data = ", h, hash->length);
00263 for (x = 0; x < hash->length; x++) {
00264 fprintf(stderr, "%02x", hash->data[x]);
00265 }
00266 fprintf(stderr, "\n");
00267 }
00268 #endif
00269
00270 root_hash_size = EVP_MD_size(merkle_path_digest);
00271 root_hash = calloc(1, root_hash_size);
00272 res = ccn_merkle_root_hash(msg, size, co, merkle_path_digest, merkle_path_info, root_hash, root_hash_size);
00273 if (res < 0) return(-1);
00274 res = EVP_VerifyUpdate(ver_ctx, root_hash, root_hash_size);
00275 if (res == 0) return(-1);
00276 res = EVP_VerifyFinal(ver_ctx, signature_bits, signature_bits_size, pkey);
00277 EVP_MD_CTX_cleanup(ver_ctx);
00278 } else {
00279
00280
00281
00282
00283 size_t signed_size = co->offset[CCN_PCO_E_Content] - co->offset[CCN_PCO_B_Name];
00284 res = EVP_VerifyUpdate(ver_ctx, msg + co->offset[CCN_PCO_B_Name], signed_size);
00285 if (res == 0) return(-1);
00286 res = EVP_VerifyFinal(ver_ctx, signature_bits, signature_bits_size, pkey);
00287 EVP_MD_CTX_cleanup(ver_ctx);
00288 }
00289 return (res);
00290 }
00291
00292 struct ccn_pkey *
00293 ccn_d2i_pubkey(const unsigned char *p, size_t size)
00294 {
00295 const unsigned char *q = p;
00296 EVP_PKEY *ans;
00297 ans = d2i_PUBKEY(NULL, &q, size);
00298 return ((struct ccn_pkey *)ans);
00299 }
00300
00301 void
00302 ccn_pubkey_free(struct ccn_pkey *i_pubkey)
00303 {
00304 EVP_PKEY *pkey = (EVP_PKEY *)i_pubkey;
00305 EVP_PKEY_free(pkey);
00306 }
00307
00308 size_t
00309 ccn_pubkey_size(const struct ccn_pkey *i_pubkey)
00310 {
00311 size_t ans;
00312 EVP_PKEY *pkey = (EVP_PKEY *)i_pubkey;
00313 ans = EVP_PKEY_size(pkey);
00314 return (ans);
00315 }
00316
00317 int
00318 ccn_append_pubkey_blob(struct ccn_charbuf *c, const struct ccn_pkey *i_pubkey)
00319 {
00320 int res;
00321 size_t bytes;
00322 unsigned char *p = NULL;
00323 res = i2d_PUBKEY((EVP_PKEY *)i_pubkey, NULL);
00324 if (res < 0)
00325 return(-1);
00326 bytes = res;
00327 res = ccn_charbuf_append_tt(c, bytes, CCN_BLOB);
00328 if (res < 0)
00329 return(-1);
00330 p = ccn_charbuf_reserve(c, bytes);
00331 if (p == NULL)
00332 return(-1);
00333 res = i2d_PUBKEY((EVP_PKEY *)i_pubkey, &p);
00334 if (res != (int)bytes)
00335 return(-1);
00336 c->length += bytes;
00337 return(bytes);
00338 }
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348 void
00349 ccn_random_bytes(unsigned char *buf, size_t size)
00350 {
00351 int num = size;
00352
00353 if (num < 0 || num != size)
00354 abort();
00355 RAND_bytes(buf, num);
00356 }
00357
00358
00359
00360
00361
00362
00363
00364
00365 void
00366 ccn_add_entropy(const void *buf, size_t size, int bits_of_entropy)
00367 {
00368 int num = size;
00369
00370 if (num < 0 || num != size)
00371 abort();
00372
00373 if (bits_of_entropy <= 0)
00374 bits_of_entropy = (num < 32) ? 1 : num / 32;
00375 RAND_add((unsigned char *)buf, num, bits_of_entropy * 0.125);
00376 }