static int attribute_public_key_tag(cxml_handler_t* const _h, cxml_tag_t * const tag) { int rc = 0; cert_cxml_handler_t * h = (cert_cxml_handler_t *)_h; if (cxml_tag_is_open(tag)){ int alg = 0, sym_alg = 0; const char * v = cxml_tag_attr_value(tag, "algorithm"); if (v) { alg = STR2ENUM(_pk_algorithms, v); if (alg < 0){ fprintf(stderr, "%s: Unknown public key algorithm\n", v); return -1; } } cint8_write(alg, &h->ptr, h->end, &rc); v = cxml_tag_attr_value(tag, "point-type"); if (v){ h->pk_ptype = STR2ENUM(_point_types, v); if (h->pk_ptype < 0){ fprintf(stderr, "%s: Unknown point type\n", v); return -1; } if (h->pk_ptype == 1) h->pk_ptype = 2; } switch (alg){ case 0: break; case 1: v = cxml_tag_attr_value(tag, "sym_alg"); if (v){ sym_alg = STR2ENUM(_sym_algorithms, v); if (sym_alg < 0){ fprintf(stderr, "%s: Unknown symmetric algorithm\n", v); return -1; } } cint8_write(sym_alg, &h->ptr, h->end, &rc); break; default: bookmark_position(h, tag); break; } h->pk_alg = alg; h->pk_sym_alg = sym_alg; } else{ if (h->pk_alg > 1){ apply_bookmark_size(h, tag); } h->pk_alg = -1; h->pk_sym_alg = -1; } return rc; }
static int certificate_subject_tag (cxml_handler_t* const _h, cxml_tag_t * const tag) { int rc = 0; cert_cxml_handler_t * h = (cert_cxml_handler_t *)_h; // write signer info if (cxml_tag_is_open(tag)){ int len; const char * v = cxml_tag_attr_value(tag, "type"); if(v == NULL){ fprintf(stderr, "Subject type must be set in Certificate profile\n"); return -1; } h->subject_type = STR2ENUM(_subject_type, v); if(h->subject_type < 0) { fprintf(stderr, "%s: Unknown subject type\n", v); return -1; } cint8_write(h->subject_type, &h->ptr, h->end, &rc); v = cxml_tag_attr_value(tag, "name"); len = cstrlen(v); if(0 == cintx_write(len, &h->ptr, h->end, &rc) && len > 0){ cbuf_write(v, len, &h->ptr, h->end, &rc); } bookmark_position(h, tag); }else{ apply_bookmark_size(h, tag); } return rc; }
static int region_id_tag (cxml_handler_t* const _h, cxml_tag_t * const tag) { int rc = 0; cert_cxml_handler_t * h = (cert_cxml_handler_t *)_h; if (cxml_tag_is_open(tag)){ int value = 0; unsigned int uvalue = 0; const char * v; // region type rc = cint8_write(4, &h->ptr, h->end, NULL); // region dictionary. use 0 by default v = cxml_tag_attr_value(tag, "dictionary"); if(v == NULL)v = cxml_tag_attr_value(tag, "dict"); if(v){ value = STR2ENUM(_id_dictionaries, v); if(value<0){ fprintf(stderr, "%s: Unknown dictionary type\n", v); return -1; } } if(cint8_write(value, &h->ptr, h->end, NULL)){ return -1; } v = cxml_tag_attr_value(tag, "id"); if(v == NULL){ fprintf(stderr, "ERROR: Region identifier must be set\n"); return -1; } while(isspace(*v))v++; uvalue = strtoul(v, NULL, 0); if(uvalue > 0xFFFF){ fprintf(stderr, "%s: Invalid region identifier\n", v); return -1; } if(cint16_write(uvalue, &h->ptr, h->end, NULL)){ return -1; } uvalue = 0; v = cxml_tag_attr_value(tag, "local"); if(v){ while(isspace(*v))v++; uvalue = strtoul(v, NULL, 0); if(!isdigit(*v) || uvalue > 0xFFFF){ fprintf(stderr, "%s: Invalid region identifier\n", v); return -1; } } cintx_write(uvalue, &h->ptr, h->end, &rc); if(rc) return -1; } return rc; }
static int certificate_signature_tag (cxml_handler_t* const _h, cxml_tag_t * const tag) { int rc = 0; cert_cxml_handler_t * h = (cert_cxml_handler_t *)_h; if (cxml_tag_is_open(tag)){ void * key; int alg = 0; if(h->signer_type == 0){ // self signed certificate key = h->verificationKey; if(!key){ fprintf(stderr, "ERROR: Verification key attribute was not provided for self-signed certificate\n"); return -1; } }else{ const char * v = cxml_tag_attr_value(tag, "algorithm"); if (v){ alg = STR2ENUM(_signature_algorithms, v); if (alg < 0){ fprintf(stderr, "%s: Unknown signature algorithm\n", v); return -1; } } if (h->signer == NULL){ fprintf(stderr, "ERROR: Signer certificate name shall be provided\n"); return -1; } // load signer certificate int plen = strlen(_searchPath) + strlen(h->signer); char * path = malloc(plen + 16); cvstrncpy(path, plen + 16, _searchPath, "/", h->signer, ".vkey", NULL); key = ecc_api_key_private_load(path, alg); if (key == NULL){ fprintf(stderr, "%s: Could not load issuing private key\n", path); free(path); return -1; } } cint8_write(alg, &h->ptr, h->end, &rc); rc = ecc_sign(key, h->buf, h->ptr - h->buf - 1, &h->ptr, h->end - h->ptr); } return rc; }
enum say_format say_format_by_name(const char *format) { return STR2ENUM(say_format, format); }
static int attribute_eccpoint_tag (cxml_handler_t* const _h, cxml_tag_t * const tag) { int rc = 0; cert_cxml_handler_t * h = (cert_cxml_handler_t *)_h; int pointtype; if (cxml_tag_is_open(tag)){ const char * v; pointtype = 0; v = cxml_tag_attr_value(tag, "type"); if (v){ pointtype = STR2ENUM(_point_types, v); if (pointtype < 0){ fprintf(stderr, "%s: Unknown point type\n", v); return -1; } if (pointtype == 1) pointtype = 2; } h->pk_ptype = pointtype; h->pk_data = NULL; h->pk_datasize = 0; } else{ void * key = h->key; pointtype = h->pk_ptype; // generate private and public key pair char x[32], y[32]; if (key == NULL){ if (h->pk_data){ if (h->pk_datasize < 32 || (h->pk_datasize < 64 && pointtype == 4)){ fprintf(stderr, "Insufficient size of public key\n"); return -1; } key = ecc_api_key_public_set(h->pk_alg, pointtype, h->pk_data, h->pk_data + 32); } else{ // generate PK if (h->pk_alg < 0 || h->pk_sym_alg < 0){ fprintf(stderr, "Public key algorythm must be specified\n"); return -1; } key = ecc_api_key_gen(h->pk_alg, h->pk_sym_alg); } } if (key){ h->key = key; rc = ecc_api_key_public(key, &x[0], &y[0]); if (rc >= 0){ if (pointtype == 2) pointtype |= (y[31] & 1); cint8_write(pointtype, &h->ptr, h->end, &rc); if (rc == 0)cbuf_write(&x[0], 32, &h->ptr, h->end, &rc); if (rc == 0 && pointtype == 4){ cbuf_write(&y[0], 32, &h->ptr, h->end, &rc); } } } if (h->pk_data){ free(h->pk_data); h->pk_data = NULL; } } return rc; }
static int subject_attribute_tag (cxml_handler_t* const _h, cxml_tag_t * const tag) { int rc = 0; cert_cxml_handler_t * h = (cert_cxml_handler_t *)_h; if (cxml_tag_is_open(tag)){ const char * v = cxml_tag_attr_value(tag, "type"); int atype; if(v == NULL){ fprintf(stderr, "Attribute type must be set\n"); return -1; } atype = STR2ENUM(_subject_attribute_types, v); if(atype < 0) { fprintf(stderr, "%s: Unknown attribute type\n", v); return -1; } cint8_write(atype, &h->ptr, h->end, &rc); h->sa_type = atype; const char * keyPath = _verificationKey; switch (h->sa_type){ case 1: // encryption_key keyPath = _decriptionKey; case 0: //verificationKey if (keyPath){ h->key = ecc_api_key_public_load(keyPath, 0); if (h->key == NULL){ fprintf(stderr, "%s: Can't load public key\n", keyPath); return -1; } } else if (_reuseKeys){ cvstrncpy(h->ptr, h->end - h->ptr, _keyPath, "/", _certName, ".", h->sa_type ? "e" : "v", "key", NULL); h->key = ecc_api_key_private_load(h->ptr, 0); if (h->key == NULL){ _reuseKeys = 0; } } break; case 32: //its_aid_list case 33: //its_aid_ssp_list bookmark_position(h, tag); break; }; }else{ switch(h->sa_type){ case 0: // verification_key h->verificationKey = h->key; h->key = NULL; break; case 1: // encryption_key h->encryptionKey = h->key; h->key = NULL; break; case 32: //its_aid_list case 33: //its_aid_ssp_list apply_bookmark_size(h, tag); break; } if(h->key){ ecc_api_key_free(h->key); } h->sa_type = -1; } return rc; }
static int certificate_signer_tag (cxml_handler_t* const _h, cxml_tag_t * const tag) { int rc = 0; // write signer info cert_cxml_handler_t * h = (cert_cxml_handler_t *)_h; if (cxml_tag_is_open(tag)){ h->signer_type = 1; // digest by default const char * v = cxml_tag_attr_value(tag, "type"); if(v){ h->signer_type = STR2ENUM(_signer_types, v); if(h->signer_type <0){ fprintf(stderr, "%s: Unknown signer type\n", v); return -1; } } cint8_write(h->signer_type, &h->ptr, h->end, &rc); if (h->signer_type > 0){ if (_signerName){ h->signer = _signerName; } else{ v = cxml_tag_attr_value(tag, "name"); if (v == NULL){ fprintf(stderr, "%s: Signer name shall be provided\n", v); return -1; } h->signer = v; } } }else{ // write signer info if (h->signer_type > 0){ if (h->signer_type > 2){ fprintf(stderr, "%d: signer method unsupported\n", h->signer_type); rc = -1; } else{ // load signer certificate int plen = strlen(_searchPath) + strlen(h->signer); char * path = malloc(plen + 16); cvstrncpy(path, plen + 16, _searchPath, "/", h->signer, ".crt", NULL); size_t size = load_certificate(path, h->ptr, h->end); if (size < 0){ fprintf(stderr, "%s: signer certificate not found or error\n", h->signer); rc = -1; } else{ if (h->signer_type == 1){ // digest char hash[sha256_hash_size]; // change eccpoint type of the signature to x_coordinate_only(0) // to follow canonical encoding h->ptr[size-65] = 0; sha256_calculate(hash, h->ptr, size); #ifdef DEBUG_DATA fprintf(stderr, "HASH (%s): ", h->signer); print_x(stderr, hash, sha256_hash_size); fprintf(stderr, "\n"); fprintf(stderr, "DIGEST (%s): ", h->signer); print_x(stderr, &hash[sha256_hash_size - 8], 8); fprintf(stderr, "\n"); #endif cbuf_write(hash + sha256_hash_size - 8, 8, &h->ptr, h->end, &rc); } else {// certificate h->ptr += size; } } free(path); } } } return rc; }