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];
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
00134
00135
00136 while (node != 1) {
00137 input_hash[node & 1] = result;
00138 input_hash[(node & 1) ^ 1] = sk_ASN1_OCTET_STRING_value(merkle_path_info->hashes, hash_index)->data;
00139 if (sk_ASN1_OCTET_STRING_value(merkle_path_info->hashes, hash_index)->length != result_size)
00140 return (-1);
00141 hash_index -= 1;
00142 #ifdef DEBUG
00143 fprintf(stderr, "node[%d].lefthash = ", parent_of(node));
00144 for (int x = 0; x < result_size; x++) {
00145 fprintf(stderr, "%02x", input_hash[0][x]);
00146 }
00147 fprintf(stderr, "\n");
00148
00149 fprintf(stderr, "node[%d].righthash = ", parent_of(node));
00150 for (int x = 0; x < result_size; x++) {
00151 fprintf(stderr, "%02x", input_hash[1][x]);
00152 }
00153 fprintf(stderr, "\n");
00154 #endif
00155 EVP_MD_CTX_init(digest_contextp);
00156 EVP_DigestInit_ex(digest_contextp, digest_type, NULL);
00157 res = EVP_DigestUpdate(digest_contextp, input_hash[0], result_size);
00158 res = EVP_DigestUpdate(digest_contextp, input_hash[1], result_size);
00159 res = EVP_DigestFinal_ex(digest_contextp, result, NULL);
00160 node = parent_of(node);
00161
00162 #ifdef DEBUG
00163 fprintf(stderr, "yielding node[%d] hash = ", node);
00164 for (int x = 0; x < result_size; x++) {
00165 fprintf(stderr, "%02x", result[x]);
00166 }
00167 fprintf(stderr, "\n");
00168 #endif
00169 }
00170 return (0);
00171 }
00172
00173 int ccn_verify_signature(const unsigned char *msg,
00174 size_t size,
00175 const struct ccn_parsed_ContentObject *co,
00176 const struct ccn_pkey *verification_pubkey)
00177 {
00178 EVP_MD_CTX verc;
00179 EVP_MD_CTX *ver_ctx = &verc;
00180 X509_SIG *digest_info = NULL;
00181 MP_info *merkle_path_info = NULL;
00182 unsigned char *root_hash;
00183 size_t root_hash_size;
00184
00185 int res;
00186
00187 const EVP_MD *digest = EVP_md_null();
00188 const EVP_MD *merkle_path_digest = EVP_md_null();
00189
00190 const unsigned char *signature_bits = NULL;
00191 size_t signature_bits_size = 0;
00192 const unsigned char *witness = NULL;
00193 size_t witness_size = 0;
00194 EVP_PKEY *pkey = (EVP_PKEY *)verification_pubkey;
00195 #ifdef DEBUG
00196 int x, h;
00197 #endif
00198
00199 res = ccn_ref_tagged_BLOB(CCN_DTAG_SignatureBits, msg,
00200 co->offset[CCN_PCO_B_SignatureBits],
00201 co->offset[CCN_PCO_E_SignatureBits],
00202 &signature_bits,
00203 &signature_bits_size);
00204 if (res < 0)
00205 return (-1);
00206
00207 if (co->offset[CCN_PCO_B_DigestAlgorithm] == co->offset[CCN_PCO_E_DigestAlgorithm]) {
00208 digest = EVP_sha256();
00209 }
00210 else {
00211
00212 fprintf(stderr, "not a DigestAlgorithm I understand right now\n");
00213 return (-1);
00214 }
00215
00216 EVP_MD_CTX_init(ver_ctx);
00217 res = EVP_VerifyInit_ex(ver_ctx, digest, NULL);
00218 if (!res)
00219 return (-1);
00220
00221 if (co->offset[CCN_PCO_B_Witness] != co->offset[CCN_PCO_E_Witness]) {
00222
00223
00224
00225
00226 res = ccn_ref_tagged_BLOB(CCN_DTAG_Witness, msg,
00227 co->offset[CCN_PCO_B_Witness],
00228 co->offset[CCN_PCO_E_Witness],
00229 &witness,
00230 &witness_size);
00231 if (res < 0)
00232 return (-1);
00233
00234
00235 digest_info = d2i_X509_SIG(NULL, &witness, witness_size);
00236
00237
00238
00239
00240 ASN1_OBJECT *merkle_hash_tree_oid = OBJ_txt2obj("1.2.840.113550.11.1.2.2", 1);
00241 if (0 != OBJ_cmp(digest_info->algor->algorithm, merkle_hash_tree_oid)) {
00242 fprintf(stderr, "A witness is present without an MHT OID!\n");
00243 ASN1_OBJECT_free(merkle_hash_tree_oid);
00244 return (-1);
00245 }
00246
00247 ASN1_OBJECT_free(merkle_hash_tree_oid);
00248 merkle_path_digest = EVP_sha256();
00249
00250 merkle_path_info = d2i_MP_info(NULL, (const unsigned char **)&(digest_info->digest->data), digest_info->digest->length);
00251 #ifdef DEBUG
00252 int node = ASN1_INTEGER_get(merkle_path_info->node);
00253 int hash_count = sk_ASN1_OCTET_STRING_num(merkle_path_info->hashes);
00254 ASN1_OCTET_STRING *hash;
00255 fprintf(stderr, "A witness is present with an MHT OID\n");
00256 fprintf(stderr, "This is node %d, with %d hashes\n", node, hash_count);
00257 for (h = 0; h < hash_count; h++) {
00258 hash = sk_ASN1_OCTET_STRING_value(merkle_path_info->hashes, h);
00259 fprintf(stderr, " hashes[%d] len = %d data = ", h, hash->length);
00260 for (x = 0; x < hash->length; x++) {
00261 fprintf(stderr, "%02x", hash->data[x]);
00262 }
00263 fprintf(stderr, "\n");
00264 }
00265 #endif
00266
00267 root_hash_size = EVP_MD_size(merkle_path_digest);
00268 root_hash = calloc(1, root_hash_size);
00269 res = ccn_merkle_root_hash(msg, size, co, merkle_path_digest, merkle_path_info, root_hash, root_hash_size);
00270 res = EVP_VerifyUpdate(ver_ctx, root_hash, root_hash_size);
00271 res = EVP_VerifyFinal(ver_ctx, signature_bits, signature_bits_size, pkey);
00272 EVP_MD_CTX_cleanup(ver_ctx);
00273 } else {
00274
00275
00276
00277
00278 size_t signed_size = co->offset[CCN_PCO_E_Content] - co->offset[CCN_PCO_B_Name];
00279 res = EVP_VerifyUpdate(ver_ctx, msg + co->offset[CCN_PCO_B_Name], signed_size);
00280 res = EVP_VerifyFinal(ver_ctx, signature_bits, signature_bits_size, pkey);
00281 EVP_MD_CTX_cleanup(ver_ctx);
00282 }
00283
00284 if (res == 1)
00285 return (1);
00286 else
00287 return (0);
00288 }
00289
00290 struct ccn_pkey *
00291 ccn_d2i_pubkey(const unsigned char *p, size_t size)
00292 {
00293 const unsigned char *q = p;
00294 EVP_PKEY *ans;
00295 ans = d2i_PUBKEY(NULL, &q, size);
00296 return ((struct ccn_pkey *)ans);
00297 }
00298
00299 void
00300 ccn_pubkey_free(struct ccn_pkey *i_pubkey)
00301 {
00302 EVP_PKEY *pkey = (EVP_PKEY *)i_pubkey;
00303 EVP_PKEY_free(pkey);
00304 }
00305
00306 size_t
00307 ccn_pubkey_size(const struct ccn_pkey *i_pubkey)
00308 {
00309 size_t ans;
00310 EVP_PKEY *pkey = (EVP_PKEY *)i_pubkey;
00311 ans = EVP_PKEY_size(pkey);
00312 return (ans);
00313 }
00314
00315 int
00316 ccn_append_pubkey_blob(struct ccn_charbuf *c, const struct ccn_pkey *i_pubkey)
00317 {
00318 int res;
00319 size_t bytes;
00320 unsigned char *p = NULL;
00321 res = i2d_PUBKEY((EVP_PKEY *)i_pubkey, NULL);
00322 if (res < 0)
00323 return(-1);
00324 bytes = res;
00325 res = ccn_charbuf_append_tt(c, bytes, CCN_BLOB);
00326 if (res < 0)
00327 return(-1);
00328 p = ccn_charbuf_reserve(c, bytes);
00329 if (p == NULL)
00330 return(-1);
00331 res = i2d_PUBKEY((EVP_PKEY *)i_pubkey, &p);
00332 if (res != (int)bytes)
00333 return(-1);
00334 c->length += bytes;
00335 return(bytes);
00336 }
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346 void
00347 ccn_random_bytes(unsigned char *buf, size_t size)
00348 {
00349 int num = size;
00350
00351 if (num < 0 || num != size)
00352 abort();
00353 RAND_bytes(buf, num);
00354 }
00355
00356
00357
00358
00359
00360
00361
00362
00363 void
00364 ccn_add_entropy(const void *buf, size_t size, int bits_of_entropy)
00365 {
00366 int num = size;
00367
00368 if (num < 0 || num != size)
00369 abort();
00370
00371 if (bits_of_entropy <= 0)
00372 bits_of_entropy = (num < 32) ? 1 : num / 32;
00373 RAND_add((unsigned char *)buf, num, bits_of_entropy * 0.125);
00374 }