00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include <string.h>
00021 #include <stdarg.h>
00022 #include <stdio.h>
00023 #include <stdlib.h>
00024 #include <sys/time.h>
00025 #include <ccn/ccn.h>
00026 #include <ccn/charbuf.h>
00027 #include <ccn/coding.h>
00028 #include <ccn/indexbuf.h>
00029 #include <ccn/signing.h>
00030 #include <ccn/ccn_private.h>
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047 int
00048 ccn_signed_info_create(struct ccn_charbuf *c,
00049 const void *publisher_key_id,
00050 size_t publisher_key_id_size,
00051 const struct ccn_charbuf *timestamp,
00052 enum ccn_content_type type,
00053 int freshness,
00054 const struct ccn_charbuf *finalblockid,
00055 const struct ccn_charbuf *key_locator)
00056 {
00057 int res = 0;
00058 const char fakepubkeyid[32] = {0};
00059
00060 if (publisher_key_id != NULL && publisher_key_id_size != 32)
00061 return(-1);
00062
00063 res |= ccn_charbuf_append_tt(c, CCN_DTAG_SignedInfo, CCN_DTAG);
00064
00065 res |= ccn_charbuf_append_tt(c, CCN_DTAG_PublisherPublicKeyDigest, CCN_DTAG);
00066 if (publisher_key_id != NULL) {
00067 res |= ccn_charbuf_append_tt(c, publisher_key_id_size, CCN_BLOB);
00068 res |= ccn_charbuf_append(c, publisher_key_id, publisher_key_id_size);
00069 } else {
00070
00071 res |= ccn_charbuf_append_tt(c, sizeof(fakepubkeyid), CCN_BLOB);
00072 res |= ccn_charbuf_append(c, fakepubkeyid, sizeof(fakepubkeyid));
00073 }
00074 res |= ccn_charbuf_append_closer(c);
00075
00076 res |= ccn_charbuf_append_tt(c, CCN_DTAG_Timestamp, CCN_DTAG);
00077 if (timestamp != NULL)
00078 res |= ccn_charbuf_append_charbuf(c, timestamp);
00079 else
00080 res |= ccnb_append_now_blob(c, CCN_MARKER_NONE);
00081 res |= ccn_charbuf_append_closer(c);
00082
00083 if (type != CCN_CONTENT_DATA) {
00084 res |= ccn_charbuf_append_tt(c, CCN_DTAG_Type, CCN_DTAG);
00085 res |= ccn_charbuf_append_tt(c, 3, CCN_BLOB);
00086 res |= ccn_charbuf_append_value(c, type, 3);
00087 res |= ccn_charbuf_append_closer(c);
00088 }
00089
00090 if (freshness >= 0)
00091 res |= ccnb_tagged_putf(c, CCN_DTAG_FreshnessSeconds, "%d", freshness);
00092
00093 if (finalblockid != NULL) {
00094 res |= ccn_charbuf_append_tt(c, CCN_DTAG_FinalBlockID, CCN_DTAG);
00095 res |= ccn_charbuf_append_charbuf(c, finalblockid);
00096 res |= ccn_charbuf_append_closer(c);
00097 }
00098
00099 if (key_locator != NULL) {
00100
00101 res |= ccn_charbuf_append_charbuf(c, key_locator);
00102 }
00103
00104 res |= ccn_charbuf_append_closer(c);
00105
00106 return(res == 0 ? 0 : -1);
00107 }
00108
00109 static int
00110 ccn_encode_Signature(struct ccn_charbuf *buf,
00111 const char *digest_algorithm,
00112 const void *witness,
00113 size_t witness_size,
00114 const struct ccn_signature *signature,
00115 size_t signature_size)
00116 {
00117 int res = 0;
00118
00119 if (signature == NULL)
00120 return(-1);
00121
00122 res |= ccn_charbuf_append_tt(buf, CCN_DTAG_Signature, CCN_DTAG);
00123
00124 if (digest_algorithm != NULL) {
00125 res |= ccn_charbuf_append_tt(buf, CCN_DTAG_DigestAlgorithm, CCN_DTAG);
00126 res |= ccn_charbuf_append_tt(buf, strlen(digest_algorithm), CCN_UDATA);
00127 res |= ccn_charbuf_append_string(buf, digest_algorithm);
00128 res |= ccn_charbuf_append_closer(buf);
00129 }
00130
00131 if (witness != NULL) {
00132 res |= ccn_charbuf_append_tt(buf, CCN_DTAG_Witness, CCN_DTAG);
00133 res |= ccn_charbuf_append_tt(buf, witness_size, CCN_BLOB);
00134 res |= ccn_charbuf_append(buf, witness, witness_size);
00135 res |= ccn_charbuf_append_closer(buf);
00136 }
00137
00138 res |= ccn_charbuf_append_tt(buf, CCN_DTAG_SignatureBits, CCN_DTAG);
00139 res |= ccn_charbuf_append_tt(buf, signature_size, CCN_BLOB);
00140 res |= ccn_charbuf_append(buf, signature, signature_size);
00141 res |= ccn_charbuf_append_closer(buf);
00142
00143 res |= ccn_charbuf_append_closer(buf);
00144
00145 return(res == 0 ? 0 : -1);
00146 }
00147
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159 int
00160 ccn_encode_ContentObject(struct ccn_charbuf *buf,
00161 const struct ccn_charbuf *Name,
00162 const struct ccn_charbuf *SignedInfo,
00163 const void *data,
00164 size_t size,
00165 const char *digest_algorithm,
00166 const struct ccn_pkey *private_key
00167 )
00168 {
00169 int res = 0;
00170 struct ccn_sigc *sig_ctx;
00171 struct ccn_signature *signature;
00172 size_t signature_size;
00173 struct ccn_charbuf *content_header;
00174 size_t closer_start;
00175
00176 content_header = ccn_charbuf_create();
00177 res |= ccn_charbuf_append_tt(content_header, CCN_DTAG_Content, CCN_DTAG);
00178 if (size != 0)
00179 res |= ccn_charbuf_append_tt(content_header, size, CCN_BLOB);
00180 closer_start = content_header->length;
00181 res |= ccn_charbuf_append_closer(content_header);
00182 if (res < 0)
00183 return(-1);
00184 sig_ctx = ccn_sigc_create();
00185 if (sig_ctx == NULL)
00186 return(-1);
00187 if (0 != ccn_sigc_init(sig_ctx, digest_algorithm))
00188 return(-1);
00189 if (0 != ccn_sigc_update(sig_ctx, Name->buf, Name->length))
00190 return(-1);
00191 if (0 != ccn_sigc_update(sig_ctx, SignedInfo->buf, SignedInfo->length))
00192 return(-1);
00193 if (0 != ccn_sigc_update(sig_ctx, content_header->buf, closer_start))
00194 return(-1);
00195 if (0 != ccn_sigc_update(sig_ctx, data, size))
00196 return(-1);
00197 if (0 != ccn_sigc_update(sig_ctx, content_header->buf + closer_start,
00198 content_header->length - closer_start))
00199 return(-1);
00200 signature = calloc(1, ccn_sigc_signature_max_size(sig_ctx, private_key));
00201 if (signature == NULL)
00202 return(-1);
00203 res = ccn_sigc_final(sig_ctx, signature, &signature_size, private_key);
00204 if (0 != res) {
00205 free(signature);
00206 return(-1);
00207 }
00208 ccn_sigc_destroy(&sig_ctx);
00209 res |= ccn_charbuf_append_tt(buf, CCN_DTAG_ContentObject, CCN_DTAG);
00210 res |= ccn_encode_Signature(buf, digest_algorithm,
00211 NULL, 0, signature, signature_size);
00212 res |= ccn_charbuf_append_charbuf(buf, Name);
00213 res |= ccn_charbuf_append_charbuf(buf, SignedInfo);
00214 res |= ccnb_append_tagged_blob(buf, CCN_DTAG_Content, data, size);
00215 res |= ccn_charbuf_append_closer(buf);
00216 free(signature);
00217 ccn_charbuf_destroy(&content_header);
00218 return(res == 0 ? 0 : -1);
00219 }
00220
00221
00222
00223
00224
00225
00226
00227
00228
00229
00230 int
00231 ccn_encode_StatusResponse(struct ccn_charbuf *buf,
00232 int errcode, const char *errtext)
00233 {
00234 int res = 0;
00235 if (errcode < 100 || errcode > 999)
00236 return(-1);
00237 res |= ccn_charbuf_append_tt(buf, CCN_DTAG_StatusResponse, CCN_DTAG);
00238 res |= ccnb_tagged_putf(buf, CCN_DTAG_StatusCode, "%d", errcode);
00239 if (errtext != NULL && errtext[0] != 0)
00240 res |= ccnb_tagged_putf(buf, CCN_DTAG_StatusText, "%s", errtext);
00241 res |= ccn_charbuf_append_closer(buf);
00242 return(res);
00243 }
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254 int
00255 ccn_charbuf_append_tt(struct ccn_charbuf *c, size_t val, enum ccn_tt tt)
00256 {
00257 unsigned char buf[1+8*((sizeof(val)+6)/7)];
00258 unsigned char *p = &(buf[sizeof(buf)-1]);
00259 int n = 1;
00260 p[0] = (CCN_TT_HBIT & ~CCN_CLOSE) |
00261 ((val & CCN_MAX_TINY) << CCN_TT_BITS) |
00262 (CCN_TT_MASK & tt);
00263 val >>= (7-CCN_TT_BITS);
00264 while (val != 0) {
00265 (--p)[0] = (((unsigned char)val) & ~CCN_TT_HBIT) | CCN_CLOSE;
00266 n++;
00267 val >>= 7;
00268 }
00269 return(ccn_charbuf_append(c, p, n));
00270 }
00271
00272 int
00273 ccn_charbuf_append_closer(struct ccn_charbuf *c)
00274 {
00275 int res;
00276 const unsigned char closer = CCN_CLOSE;
00277 res = ccn_charbuf_append(c, &closer, 1);
00278 return(res);
00279 }
00280
00281
00282
00283
00284
00285
00286
00287 int
00288 ccnb_append_number(struct ccn_charbuf *c, int nni)
00289 {
00290 char nnistring[40];
00291 int nnistringlen;
00292 int res;
00293
00294 if (nni < 0)
00295 return(-1);
00296 nnistringlen = snprintf(nnistring, sizeof(nnistring), "%d", nni);
00297 if (nnistringlen >= sizeof(nnistring))
00298 return(-1);
00299 res = ccn_charbuf_append_tt(c, nnistringlen, CCN_UDATA);
00300 res |= ccn_charbuf_append_string(c, nnistring);
00301 return(res);
00302 }
00303
00304
00305
00306
00307
00308
00309
00310
00311
00312
00313
00314
00315 int
00316 ccnb_append_timestamp_blob(struct ccn_charbuf *c,
00317 enum ccn_marker marker,
00318 intmax_t secs, int nsecs)
00319 {
00320 int i;
00321 int n;
00322 intmax_t ts;
00323 unsigned char *p;
00324 if (secs <= 0 || nsecs < 0 || nsecs > 999999999)
00325 return(-1);
00326 n = 2;
00327 for (ts = secs >> 4; n < 7 && ts != 0; ts >>= 8)
00328 n++;
00329 ccn_charbuf_append_tt(c, n + (marker >= 0), CCN_BLOB);
00330 if (marker >= 0)
00331 ccn_charbuf_append_value(c, marker, 1);
00332 p = ccn_charbuf_reserve(c, n);
00333 if (p == NULL)
00334 return(-1);
00335 ts = secs >> 4;
00336 for (i = 0; i < n - 2; i++)
00337 p[i] = ts >> (8 * (n - 3 - i));
00338
00339 ts = ((secs & 15) << 12) + ((nsecs / 5 * 8 + 195312) / 390625);
00340 for (i = n - 2; i < n; i++)
00341 p[i] = ts >> (8 * (n - 1 - i));
00342 c->length += n;
00343 return(0);
00344 }
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354 int
00355 ccnb_append_now_blob(struct ccn_charbuf *c, enum ccn_marker marker)
00356 {
00357 struct timeval now;
00358 int res;
00359
00360 gettimeofday(&now, NULL);
00361 res = ccnb_append_timestamp_blob(c, marker, now.tv_sec, now.tv_usec * 1000);
00362 return(res);
00363 }
00364
00365
00366
00367
00368 int
00369 ccnb_element_begin(struct ccn_charbuf *c, enum ccn_dtag dtag)
00370 {
00371 return(ccn_charbuf_append_tt(c, dtag, CCN_DTAG));
00372 }
00373
00374
00375
00376
00377
00378
00379 int ccnb_element_end(struct ccn_charbuf *c)
00380 {
00381 return(ccn_charbuf_append_closer(c));
00382 }
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394 int
00395 ccnb_append_tagged_blob(struct ccn_charbuf *c,
00396 enum ccn_dtag dtag,
00397 const void *data,
00398 size_t size)
00399 {
00400 int res;
00401
00402 res = ccn_charbuf_append_tt(c, dtag, CCN_DTAG);
00403 if (size != 0) {
00404 res |= ccn_charbuf_append_tt(c, size, CCN_BLOB);
00405 res |= ccn_charbuf_append(c, data, size);
00406 }
00407 res |= ccn_charbuf_append_closer(c);
00408 return(res == 0 ? 0 : -1);
00409 }
00410
00411
00412
00413
00414
00415
00416
00417
00418
00419
00420 int
00421 ccnb_tagged_putf(struct ccn_charbuf *c,
00422 enum ccn_dtag dtag, const char *fmt, ...)
00423 {
00424 int res;
00425 int size;
00426 va_list ap;
00427 char *ptr;
00428
00429 res = ccn_charbuf_append_tt(c, dtag, CCN_DTAG);
00430 if (res < 0)
00431 return(-1);
00432 ptr = (char *)ccn_charbuf_reserve(c, strlen(fmt) + 20);
00433 if (ptr == NULL)
00434 return(-1);
00435 va_start(ap, fmt);
00436 size = vsnprintf(ptr + 2, (c->limit - c->length - 2), fmt, ap);
00437 va_end(ap);
00438 if (size < 0)
00439 return(-1);
00440 if (size > 0) {
00441 if (size >= (c->limit - c->length - 2))
00442 ptr = NULL;
00443 res |= ccn_charbuf_append_tt(c, size, CCN_UDATA);
00444 if (ptr == (char *)c->buf + c->length + 2)
00445 c->length += size;
00446 else if (ptr == (char *)c->buf + c->length + 1) {
00447 memmove(ptr - 1, ptr, size);
00448 c->length += size;
00449 }
00450 else {
00451 ptr = (char *)ccn_charbuf_reserve(c, size + 1);
00452 va_start(ap, fmt);
00453 size = vsnprintf(ptr, size + 1, fmt, ap);
00454 va_end(ap);
00455 if (size < 0)
00456 return(-1);
00457 c->length += size;
00458 }
00459 }
00460 res |= ccn_charbuf_append_closer(c);
00461 return(res == 0 ? 0 : -1);
00462 }
00463