daeElement *daeSIDResolver::findSID( daeElement *el, daeString sid ) { //first check yourself daeString *s = (daeString*)el->getAttributeValue( "sid" ); if ( s != NULL && *s != NULL && strcmp( *s, sid ) == 0 ) { //found it return el; } //and if you are a instance_* then check what you point to daeString nm = el->getElementName(); if ( nm == NULL ) { nm = el->getTypeName(); } if ( strncmp( nm, "instance_", 9 ) == 0 ) { daeURI *uri = (daeURI*)el->getAttributeValue("url"); if ( uri != NULL && uri->getElement() != NULL ) { daeElement *e = findSID( uri->getElement(), sid ); if ( e != NULL ) { //found it return e; } } } daeElementRefArray children; el->getChildren( children ); size_t cnt = children.getCount(); for ( size_t x = 0; x < cnt; x++ ) { //examine the children //char s[56]; //daeAtomicType::get( "token" )->memoryToString( children[x]->getAttributeValue( "sid" ), s, 56 ); daeString *s = (daeString*)children[x]->getAttributeValue( "sid" ); if ( s != NULL && *s != NULL && strcmp( *s, sid ) == 0 ) { //found it return children[x]; } } for ( size_t x = 0; x < cnt; x++ ) { //if not found look for it in each child if ( profile != NULL && strcmp( children[x]->getTypeName(), "technique_COMMON" ) == 0 ) { //not looking for common profile continue; } else if ( strcmp( children[x]->getTypeName(), "technique" ) == 0 && children[x]->hasAttribute( "profile" ) ) { if ( profile == NULL || strcmp( profile, children[x]->getAttributeValue( "profile" ) ) != 0 ) { //not looking for this technique profile continue; } } daeElement *e = findSID( children[x], sid ); if ( e != NULL ) { //found it return e; } } return NULL; }
const char *signCMS( struct CMS *cms, const char *keyfilename, bool bad) { bool hashContext_initialized = false; CRYPT_CONTEXT hashContext; bool sigKeyContext_initialized = false; CRYPT_CONTEXT sigKeyContext; CRYPT_KEYSET cryptKeyset; int signatureLength; int tbs_lth; char *msg = (char *)0; uchar *tbsp; uchar *signature = NULL; uchar hash[40]; struct casn *sidp; struct Attribute *attrp; struct AttrTableDefined *attrtdp; struct SignerInfo *sigInfop; // signer info // firat clear out any old stuff in signerInfos that may have been put // there by old code while (num_items(&cms->content.signedData.signerInfos.self) > 0) eject_casn(&cms->content.signedData.signerInfos.self, 0); sigInfop = (struct SignerInfo *) inject_casn(&(cms->content.signedData.signerInfos.self), 0); // write the signature version (3) to the signer info write_casn_num(&sigInfop->version.self, 3); // find the SID if ((sidp = findSID(cms)) == NULL) return "finding SID"; // copy the CMS's SID over to the signature's SID copy_casn(&sigInfop->sid.subjectKeyIdentifier, sidp); // use sha256 as the algorithm write_objid(&sigInfop->digestAlgorithm.algorithm, id_sha256); // no parameters to sha256 write_casn(&sigInfop->digestAlgorithm.parameters.sha256, (uchar *) "", 0); // first attribute: content type attrp = (struct Attribute *)inject_casn(&sigInfop->signedAttrs.self, 0); write_objid(&attrp->attrType, id_contentTypeAttr); attrtdp = (struct AttrTableDefined *)inject_casn(&attrp->attrValues.self, 0); copy_casn(&attrtdp->contentType, &cms->content.signedData.encapContentInfo.eContentType); // second attribute: message digest attrp = (struct Attribute *)inject_casn(&sigInfop->signedAttrs.self, 1); write_objid(&attrp->attrType, id_messageDigestAttr); // create the hash for the content // first pull out the content if ((tbs_lth = readvsize_casn(&cms->content.signedData.encapContentInfo.eContent. self, &tbsp)) < 0) return "getting content"; // set up the context, initialize crypt memset(hash, 0, 40); if (cryptInit_wrapper() != CRYPT_OK) return "initializing cryptlib"; // the following calls function f, and if f doesn't return 0 sets // msg to m, then breaks out of the loop. Used immediately below. #define CALL(f,m) if (f != 0) { msg = m; break; } // use a "do { ... } while (0)" loop to bracket this code, so we can // bail out on failure. (Note that this construct isn't really a // loop; it's a way to use break as a more clean version of goto.) do { // first sign the body of the message // create the context CALL(cryptCreateContext(&hashContext, CRYPT_UNUSED, CRYPT_ALGO_SHA2), "creating context"); hashContext_initialized = true; // generate the hash CALL(cryptEncrypt(hashContext, tbsp, tbs_lth), "hashing"); CALL(cryptEncrypt(hashContext, tbsp, 0), "hashing"); // get the hash value. then we're done, so destroy it CALL(cryptGetAttributeString (hashContext, CRYPT_CTXINFO_HASHVALUE, hash, &signatureLength), "getting first hash"); CALL(cryptDestroyContext(hashContext), "destroying intermediate context"); // insert the hash as the first attribute attrtdp = (struct AttrTableDefined *)inject_casn(&attrp->attrValues.self, 0); write_casn(&attrtdp->messageDigest, hash, signatureLength); // create signing time attribute; mark the signing time as now if (getenv("RPKI_NO_SIGNING_TIME") == NULL) { attrp = (struct Attribute *)inject_casn(&sigInfop->signedAttrs.self, 2); write_objid(&attrp->attrType, id_signingTimeAttr); attrtdp = (struct AttrTableDefined *)inject_casn(&attrp->attrValues.self, 0); write_casn_time(&attrtdp->signingTime.utcTime, time((time_t *) 0)); } // we are all done with the content free(tbsp); // now sign the attributes // get the size of signed attributes and allocate space for them if ((tbs_lth = size_casn(&sigInfop->signedAttrs.self)) < 0) { msg = "sizing SignerInfo"; break; } tbsp = (uchar *) calloc(1, tbs_lth); encode_casn(&sigInfop->signedAttrs.self, tbsp); *tbsp = ASN_SET; // create a new, fresh hash context for hashing the attrs, and hash // them CALL(cryptCreateContext(&hashContext, CRYPT_UNUSED, CRYPT_ALGO_SHA2), "creating hash context"); CALL(cryptEncrypt(hashContext, tbsp, tbs_lth), "hashing attrs"); CALL(cryptEncrypt(hashContext, tbsp, 0), "hashing attrs"); // get the hash value CALL(cryptGetAttributeString (hashContext, CRYPT_CTXINFO_HASHVALUE, hash, &signatureLength), "getting attr hash"); // get the key and sign it CALL(cryptKeysetOpen (&cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE, keyfilename, CRYPT_KEYOPT_READONLY), "opening key set"); CALL(cryptCreateContext(&sigKeyContext, CRYPT_UNUSED, CRYPT_ALGO_RSA), "creating RSA context"); sigKeyContext_initialized = true; CALL(cryptGetPrivateKey (cryptKeyset, &sigKeyContext, CRYPT_KEYID_NAME, "label", "password"), "getting key"); CALL(cryptCreateSignature (NULL, 0, &signatureLength, sigKeyContext, hashContext), "signing"); // check the signature to make sure it's right signature = (uchar *) calloc(1, signatureLength + 20); // second parameter is signatureMaxLength, so we allow a little more CALL(cryptCreateSignature (signature, signatureLength + 20, &signatureLength, sigKeyContext, hashContext), "signing"); // verify that the signature is right CALL(cryptCheckSignature (signature, signatureLength, sigKeyContext, hashContext), "verifying"); // end of protected block } while (0); // done with cryptlib, shut it down if (hashContext_initialized) { cryptDestroyContext(hashContext); hashContext_initialized = false; } if (sigKeyContext_initialized) { cryptDestroyContext(sigKeyContext); sigKeyContext_initialized = false; } // did we have any trouble above? if so, bail if (msg != 0) { return msg; } // ok, write the signature back to the object struct SignerInfo sigInfo; SignerInfo(&sigInfo, (ushort) 0); decode_casn(&sigInfo.self, signature); // were we supposed to make a bad signature? if so, make it bad if (bad) { uchar *sig; int siz = readvsize_casn(&sigInfo.signature, &sig); sig[0]++; write_casn(&sigInfo.signature, sig, siz); free(sig); } // copy the signature into the object copy_casn(&sigInfop->signature, &sigInfo.signature); delete_casn(&sigInfo.self); // all done with it now free(signature); // Mark it as encrypted with rsa, no params. // See http://www.ietf.org/mail-archive/web/sidr/current/msg04813.html for // why we use id_rsadsi_rsaEncryption instead of id_sha_256WithRSAEncryption // here. write_objid(&sigInfop->signatureAlgorithm.algorithm, id_rsadsi_rsaEncryption); write_casn(&sigInfop->signatureAlgorithm.parameters.self, (uchar *) "", 0); // no errors, we return NULL return NULL; }
void daeSIDResolver::resolve() { char * str = (char *)target; char * pos = strchr( str, '/'); char * id; if ( pos == NULL ) { pos = strchr( str, '.' ); } if ( pos == NULL ) { pos = strchr( str, '(' ); } if ( pos != NULL ) { id = new char[ pos - str + 1 ]; strncpy( id, str, pos - str ); id[ pos - str ] = 0; str = pos; } else { id = new char[ strlen( str ) + 1 ]; strcpy( id, str ); str = str + strlen( str ); } if ( strcmp( id, "." ) == 0 ) { element = container; state = sid_success_element; } else { daeIDRef idref( id ); idref.setContainer( container ); idref.resolveElement(); if ( idref.getState() != daeIDRef::id_success ) { state = sid_failed_not_found; delete[] id; element = NULL; return; } element = idref.getElement(); state = sid_success_element; } char * next = NULL; while ( *str != '.' && *str != '(' && *str != 0 ) { if ( *str == '/' ) { str++; } if ( next != NULL ) { delete[] next; next = NULL; } pos = strchr( str, '/'); if ( pos == NULL ) { pos = strchr( str, '.' ); } if ( pos == NULL ) { pos = strchr( str, '(' ); } if ( pos != NULL ) { next = new char[ pos - str + 1 ]; strncpy( next, str, pos - str ); next[ pos - str ] = 0; str = pos; } else { next = new char[ strlen( str ) + 1 ]; strcpy( next, str ); str = str + strlen( str ); } //find the child element with SID of next daeElement *el = findSID( element, next ); element = el; if ( element == NULL ) { //failed state = sid_failed_not_found; if ( id != NULL ) { delete[] id; } if ( next != NULL ) { delete[] next; next = NULL; } return; } } //check for the double array if ( strcmp( element->getTypeName(), "source" ) == 0 ) { daeElementRefArray children; element->getChildren( children ); size_t cnt = children.getCount(); for ( size_t x = 0; x < cnt; x++ ) { if ( strcmp( children[x]->getTypeName(), "float_array" ) == 0 ) { doubleArray = (daeDoubleArray*)children[x]->getMeta()->getValueAttribute()->getWritableMemory( children[x] ); state = sid_success_array; break; } } } else { daeMetaAttribute *ma = element->getMeta()->getValueAttribute(); if ( ma != NULL ) { if ( ma->isArrayAttribute() && ma->getType()->getTypeEnum() == daeAtomicType::DoubleType ) { doubleArray = (daeDoubleArray*)ma->getWritableMemory( element ); state = sid_success_array; } } } if( state == sid_success_array ) { //found the double array if ( *str == '.' ) { //do the double lookup stuff based on COMMON profile offset str++; if ( strcmp( str, "ANGLE" ) == 0 ) { doublePtr = &(doubleArray->get(3)); state = sid_success_double; } else if ( strlen( str ) == 1 ) { switch ( *str ) { case 'X': case 'R': case 'U': case 'S': doublePtr = &(doubleArray->get(0)); state = sid_success_double; break; case 'Y': case 'G': case 'V': case 'T': doublePtr = &(doubleArray->get(1)); state = sid_success_double; break; case 'Z': case 'B': case 'P': doublePtr = &(doubleArray->get(2)); state = sid_success_double; break; case 'W': case 'A': case 'Q': doublePtr = &(doubleArray->get(3)); state = sid_success_double; break; }; } } else if ( *str == '(' ) { //do the double lookup stuff based on the offset given str++; pos = strchr( str, '(' ); daeInt i = atoi( str ); if ( pos != NULL && doubleArray->getCount() == 16 ) { //we are doing a matrix lookup pos++; daeInt j = atoi( pos ); doublePtr = &(doubleArray->get( i*4 + j )); state = sid_success_double; } else { //vector lookup if ( (daeInt)doubleArray->getCount() > i ) { doublePtr = &(doubleArray->get(i)); state = sid_success_double; } } } } if ( id != NULL ) { delete[] id; } if ( next != NULL ) { delete[] next; } }