int sm_SignMessage ( unsigned char **signedMessage, /* OUT */ size_t *signedMessageLen, /* OUT */ unsigned char *tbs, /* IN data to sign */ size_t tbsLen, /* IN length of `tbs' */ int nested, /* IN */ const char *contentType, /* IN type of `tbs' */ const char *digestAlgorithm, /* IN */ const unsigned char *digestParam, /* IN */ size_t digestParamSize, /* IN */ const char *signatureAlgorithm, /* IN */ const unsigned char *sigParam, /* IN */ size_t sigParamSize, /* IN */ PKICertificate *signerCertificate, /* IN */ PKIAttributes *signedAttributes, /* IN (optional) */ List *includeCerts, /* IN (optional) */ HashCallback *hashCallback, /* IN */ void *hashCallbackData, /* IN (optional) */ SignCallback *signCallback, /* IN */ void *signCallbackData, /* IN (optional) */ PKICONTEXT *ctx) /* IN */ { PKIContentInfo contentInfo; PKISignedData *signedData; PKISignerInfo *signerInfo; PKIOBJECT_ID *digestOID; PKIOBJECT_ID *contentOID; PKIOBJECT_ID *signatureOID; PKIOBJECT_ID *contentTypeOID; PKIOBJECT_ID *signedDataOID; PKIANY asnBlock; PKIANY digestValue; int err = 0; int i; size_t msgLen; unsigned char *msg; int result; unsigned char *pcontent; size_t pcontentlen; signedData = PKINewSignedData (ctx); /* CMS states that the version is 1 if no attribute certificates are present and the underlying content type is id-data */ PKIPutIntVal (ctx, &signedData->version, (!strcmp (contentType, SM_OID_CONTENT_DATA)) ? 1 : 3); signedData->digestAlgorithms.n = 1; signedData->digestAlgorithms.elt[0] = PKINewDigestAlgorithmIdentifier (ctx); digestOID = sm_StringToOID (digestAlgorithm, ctx); PKIPutOctVal (ctx, &signedData->digestAlgorithms.elt[0]->algorithm, digestOID->val, digestOID->len); if (digestParamSize) { signedData->digestAlgorithms.elt[0]->parameters = PKINewANY (ctx); PKIPutOctVal (ctx, signedData->digestAlgorithms.elt[0]->parameters, digestParam, digestParamSize); } contentOID = sm_StringToOID (contentType, ctx); PKIPutOctVal (ctx, &signedData->contentInfo.contentType, contentOID->val, contentOID->len); /* add the data that is being signed */ signedData->contentInfo.content = PKINewANY (ctx); /* if we have type Data, it must be encoded as OCTET STRING */ if (strcmp (contentType, SM_OID_CONTENT_DATA) == 0) { PKIOCTET_STRING *content; content = PKINewOCTET_STRING (ctx); PKIPutOctVal (ctx, content, tbs, tbsLen); signedData->contentInfo.content->len = PKISizeofOCTET_STRING (ctx, content, 1); signedData->contentInfo.content->val = PKIAlloc (ctx->memMgr, signedData->contentInfo.content->len); PKIPackOCTET_STRING (ctx, signedData->contentInfo.content->val, signedData->contentInfo.content->len, content, &err); PKIFreeOCTET_STRING (ctx, content); if (err) return PKCS7_ERROR_UNKNOWN; pcontent = tbs; pcontentlen = tbsLen; } else { PKIPutOctVal (ctx, signedData->contentInfo.content, tbs, tbsLen); /* when signing, the type and length octets are not included in the hash */ pcontent = tbs + 1; pcontent += PKIGetLength (pcontent, &pcontentlen); } signedData->signerInfos.n = 1; signerInfo = signedData->signerInfos.elt[0] = PKINewSignerInfo (ctx); PKIPutIntVal (ctx, &signerInfo->version, 1); /* version 1 */ sm_CopyIssuerAndSerialNumber (&signerInfo->issuerAndSerialNumber, signerCertificate, ctx); PKIPutOctVal (ctx, &signerInfo->digestAlgorithm.algorithm, digestOID->val, digestOID->len); PKIFreeOBJECT_ID (ctx, digestOID); if (digestParamSize) { signerInfo->digestAlgorithm.parameters = PKINewANY (ctx); PKIPutOctVal (ctx, signerInfo->digestAlgorithm.parameters, digestParam, digestParamSize); } if (signedAttributes || (strcmp (contentType, SM_OID_CONTENT_DATA))) { contentTypeOID = sm_StringToOID (SM_OID_CONTENT_TYPE, ctx); signerInfo->authenticatedAttributes = PKINewAttributes (ctx); /* add the id-contentType attribute */ memset (&asnBlock, 0, sizeof (asnBlock)); asnBlock.len = PKISizeofOBJECT_ID (ctx, contentOID, 1); asnBlock.val = PKIAlloc (ctx->memMgr, asnBlock.len); PKIPackOBJECT_ID (ctx, asnBlock.val, asnBlock.len, contentOID, &err); sm_AddSimpleAttribute (signerInfo->authenticatedAttributes, contentTypeOID, &asnBlock, ctx); PKIFree (ctx->memMgr, asnBlock.val); PKIFreeOBJECT_ID (ctx, contentTypeOID); /* add the id-messageDigest attribute */ result = hashCallback (&digestValue, digestAlgorithm, pcontent, pcontentlen, hashCallbackData, ctx); if (result != PKCS7_OK) return (result); memset (&asnBlock, 0, sizeof (asnBlock)); err = 0; asnBlock.len = PKISizeofOCTET_STRING (ctx, &digestValue, 1); asnBlock.val = PKIAlloc (ctx->memMgr, asnBlock.len); PKIPackOCTET_STRING (ctx, asnBlock.val, asnBlock.len, &digestValue, &err); contentTypeOID = sm_StringToOID (SM_OID_MESSAGE_DIGEST, ctx); sm_AddSimpleAttribute (signerInfo->authenticatedAttributes, contentTypeOID, &asnBlock, ctx); PKIFreeOBJECT_ID (ctx, contentTypeOID); PKIFree (ctx->memMgr, asnBlock.val); PKIFree (ctx->memMgr, digestValue.val); /* add the user specified attributes */ if (signedAttributes) { for (i = 0; i < signedAttributes->n; i++) { signerInfo->authenticatedAttributes->elt[signerInfo->authenticatedAttributes->n++] = sm_CopyAttribute (signedAttributes->elt[i], ctx); } } /* if auth attributes are present, we sign the DER of it. the body of the message is protected by the fact that the hash value is included as an attribute */ msgLen = PKISizeofAttributes (ctx, signerInfo->authenticatedAttributes, 1); msg = PKIAlloc (ctx->memMgr, msgLen); PKIPackAttributes (ctx, msg, msgLen, signerInfo->authenticatedAttributes, &err); if (err) return PKCS7_ERROR_ATTRIBUTES; } else { /* otherwise sign the data itself */ msgLen = pcontentlen; msg = PKIAlloc (ctx->memMgr, msgLen); memcpy (msg, pcontent, pcontentlen); } PKIFreeOBJECT_ID (ctx, contentOID); result = signCallback ( &signerInfo->encryptedDigest, digestAlgorithm, signatureAlgorithm, signerCertificate, msg, msgLen, signCallbackData, ctx); PKIFree (ctx->memMgr, msg); if (result != PKCS7_OK) return (result); signatureOID = sm_StringToOID (signatureAlgorithm, ctx); PKIPutOctVal (ctx, &signerInfo->digestEncryptionAlgorithm.algorithm, signatureOID->val, signatureOID->len); PKIFreeOBJECT_ID (ctx, signatureOID); if (sigParamSize) { signerInfo->digestEncryptionAlgorithm.parameters = PKINewANY (ctx); PKIPutOctVal (ctx, signerInfo->digestEncryptionAlgorithm.parameters, sigParam, sigParamSize); } if (includeCerts) { List *pCert; int certCount = 0; signedData->certificates = PKINewExtendedCertificatesAndCertificates(ctx); for (pCert = includeCerts; pCert; pCert = pCert->next, certCount++) { unsigned char *certData; size_t certLen; PKICertificate *tCert = (PKICertificate *) pCert->data; int asnError = 0; certLen = PKISizeofCertificate (ctx, tCert, 1); certData = PKIAlloc (ctx->memMgr, certLen); PKIPackCertificate (ctx, certData, certLen, tCert, &asnError); if (asnError) { PKIFree (ctx->memMgr, certData); continue; } signedData->certificates->elt[certCount] = PKIAlloc (ctx->memMgr, sizeof (PKIExtendedCertificateOrCertificate)); signedData->certificates->elt[certCount]->CHOICE_field_type = PKIID_Certificate; PKIUnpackCertificate (ctx, (PKICertificate **) &signedData->certificates->elt[certCount]->data, certData, certLen, &asnError); PKIFree (ctx->memMgr, certData); } signedData->certificates->n = certCount; } if (nested) { /* when doing nested protection, the ContentInfo header will be present in the upper level SignedData or EnvelopedData, so just return the SignedData object directly */ *signedMessageLen = PKISizeofSignedData (ctx, signedData, 1); *signedMessage = PKIAlloc (ctx->memMgr, *signedMessageLen); PKIPackSignedData (ctx, *signedMessage, *signedMessageLen, signedData, &err); } else { signedDataOID = sm_StringToOID (SM_OID_CONTENT_SIGNED_DATA, ctx); memset (&contentInfo, 0, sizeof (contentInfo)); PKIPutOctVal (ctx, &contentInfo.contentType, signedDataOID->val, signedDataOID->len); PKIFreeOCTET_STRING (ctx, signedDataOID); contentInfo.content = PKINewANY (ctx); contentInfo.content->len = PKISizeofSignedData (ctx, signedData, 1); contentInfo.content->val = PKIAlloc (ctx->memMgr, contentInfo.content->len); PKIPackSignedData (ctx, contentInfo.content->val, contentInfo.content->len, signedData, &err); /* pack up the final version of the message */ *signedMessageLen = PKISizeofContentInfo (ctx, &contentInfo, 1); *signedMessage = PKIAlloc (ctx->memMgr, *signedMessageLen); PKIPackContentInfo (ctx, *signedMessage, *signedMessageLen, &contentInfo, &err); PKIDropInPlaceContentInfo (ctx, &contentInfo); } PKIFreeSignedData (ctx, signedData); return 0; }
void CGHostGenie :: EventBNETHashRequest( const EventBNETHashRequestData &data ) { if( hashCallback != NULL ) hashCallback( callbackObject, data ); }