const char *signCMSBlob( struct CMSBlob *cms, const char *keyfilename) { bool sigKeyContext_initialized = false; CRYPT_CONTEXT sigKeyContext; CRYPT_KEYSET cryptKeyset; bool hashContext_initialized = false; CRYPT_CONTEXT hashContext; int tbs_lth; /* to-be-signed length */ unsigned char *tbsp = NULL; /* to-be-signed pointer */ unsigned char *hash[40]; /* stores sha256 message digest */ int signatureLength; /* RSA signature length */ unsigned char *signature = NULL; /* RSA signature bytes */ const char *errmsg = NULL; struct SignerInfo *signerInfop = (struct SignerInfo *)member_casn(&cms->content.signedData.signerInfos. self, 0); struct BlobEncapsulatedContentInfo *encapContentInfop = &cms->content.signedData.encapContentInfo; if (vsize_casn(&signerInfop->signedAttrs.self) == 0) { if ((tbs_lth = vsize_casn(&encapContentInfop->eContent)) < 0) { errmsg = "sizing eContent"; return errmsg; } tbsp = (unsigned char *)calloc(1, tbs_lth); if (!tbsp) { errmsg = "out of memory"; return errmsg; } tbs_lth = read_casn(&encapContentInfop->eContent, tbsp); } else { // get the size of signed attributes and allocate space for them if ((tbs_lth = size_casn(&signerInfop->signedAttrs.self)) < 0) { errmsg = "sizing SignerInfo"; return errmsg; } tbsp = (unsigned char *)calloc(1, tbs_lth); if (!tbsp) { errmsg = "out of memory"; return errmsg; } // DER-encode signedAttrs tbs_lth = encode_casn(&signerInfop->signedAttrs.self, tbsp); *tbsp = ASN_SET; /* replace ASN.1 identifier octet with ASN_SET * (0x31) */ } // compute SHA-256 of signedAttrs if (cryptCreateContext(&hashContext, CRYPT_UNUSED, CRYPT_ALGO_SHA2) < 0 || !(hashContext_initialized = true)) errmsg = "creating hash context"; else if (cryptEncrypt(hashContext, tbsp, tbs_lth) < 0 || cryptEncrypt(hashContext, tbsp, 0) < 0) errmsg = "hashing attrs"; else if (cryptGetAttributeString(hashContext, CRYPT_CTXINFO_HASHVALUE, hash, &signatureLength) < 0) errmsg = "getting attr hash"; // get the key and sign it else if (cryptKeysetOpen(&cryptKeyset, CRYPT_UNUSED, CRYPT_KEYSET_FILE, keyfilename, CRYPT_KEYOPT_READONLY) < 0) errmsg = "opening key set"; else if (cryptCreateContext(&sigKeyContext, CRYPT_UNUSED, CRYPT_ALGO_RSA) < 0 || !(sigKeyContext_initialized = true)) errmsg = "creating RSA context"; else if (cryptGetPrivateKey(cryptKeyset, &sigKeyContext, CRYPT_KEYID_NAME, "label", "password") < 0) errmsg = "getting key"; else if (cryptCreateSignature(NULL, 0, &signatureLength, sigKeyContext, hashContext) < 0) errmsg = "signing"; // compute signature else if ((signature = (unsigned char *)calloc(1, signatureLength + 20)) == 0) errmsg = "out of memory"; // second parameter is signatureMaxLength, so we allow a little more else if (cryptCreateSignature (signature, signatureLength + 20, &signatureLength, sigKeyContext, hashContext) < 0) errmsg = "signing"; // verify that the signature is right else if (cryptCheckSignature(signature, signatureLength, sigKeyContext, hashContext) < 0) errmsg = "verifying"; if (hashContext_initialized) { cryptDestroyContext(hashContext); hashContext_initialized = false; } if (sigKeyContext_initialized) { cryptDestroyContext(sigKeyContext); sigKeyContext_initialized = false; } if (!errmsg) { struct SignerInfo sigInfo; SignerInfo(&sigInfo, (ushort) 0); decode_casn(&sigInfo.self, signature); // copy the signature into the object copy_casn(&signerInfop->signature, &sigInfo.signature); delete_casn(&sigInfo.self); } if (signature) free(signature); if (tbsp) free(tbsp); return errmsg; }
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; }
int funcion6() { int valido, tamFirma, tam, tamCert, i, status, keySize, keyMaxSize; long opcion_l; char opcion[5], *ptr, *endptr, *buffer, *rutaToCheck, *rutaFirma, *nombreFirma, *firma, *cert, *nombreCert, *rutaCert; FILE *ptrFileToCheck, *ptrFirma, *ptrCert; DIR *dir; struct dirent *ent; struct stat st; /*Reservo memoria*/ rutaToCheck=(char *)malloc(120); rutaFirma=(char *)malloc(120); nombreFirma=(char *)malloc(50); nombreCert=(char *)malloc(50); rutaCert=(char *)malloc(120); system("clear"); printf("\n ------------------------------------\n"); printf("| Verificar firma |\n"); printf(" ------------------------------------\n\n"); fflush(stdout); /*PASO 1. Ruta del archivo a verificar*/ do { valido=0; printf("PASO 1. Introduzca la ruta del archivo que desea verificar: "); scanf("%s", rutaToCheck); if((ptrFileToCheck=fopen(rutaToCheck, "rb")) == NULL ) { printf("No se encuentra el archivo. Revise la ruta :)\n\n"); valido=1; fflush(stdout); } } while(valido==1); /*Necesitamos abrir el archivo y volcarlo a memoria*/ stat(rutaToCheck, &st); tam=st.st_size; buffer=(char *)malloc(tam); fread(buffer, 1, tam, ptrFileToCheck); /*Buscamos el caracter '/' dentro de la cadena. Si está, es porque el usuario metió la ruta completa*/ if((ptr=(strrchr(rutaToCheck, '/')))!=NULL) sprintf(nombreFirma, "%s.p7s", ptr+1); //Ruta completa else sprintf(nombreFirma, "%s.p7s", rutaToCheck); //El usuario metió el nombre del archivo /*Ahora tengo que leer la firma. Primero la busco, y si no está, que la seleccione el usuario*/ dir = opendir ("./Firmas digitales/"); if (dir != NULL) { i=0; /* Vamos a buscar los archivos .p7s que correspondan*/ while ((ent = readdir (dir)) != NULL) { if((ptr=strstr(ent->d_name, nombreFirma))!=NULL) { i++; } } closedir(dir); } else { /* Problemas al abrir el directorio */ printf("¿Ha ejecutado ya la opción 5?\n"); fflush(stdout); return(-1); } if(i==0) { //Resultados = 0 printf("\nNo se ha encontrado una firma adecuada\n"); fflush(stdout); printf("Seleccione cuál de los siguientes archivos corresponde con la firma creada en la función 5:\n "); fflush(stdout); dir = opendir ("./Firmas digitales/"); /* Nos va a mostrar los archivos .p15 que haya dentro de la carpeta Claves y cert.*/ while ((ent = readdir (dir)) != NULL) { if((ptr=strstr(ent->d_name, ".p7s"))!=NULL) { i++; printf(" %d. %s\n", i, ent->d_name); } } closedir(dir); /*El usuario introduce el número que corresponde a la firma que elija*/ do{ valido=0; printf("Introduzca el número de la firma que desea usar >> "); scanf("%s", &opcion); opcion_l = strtol(opcion,&endptr,10); if(strlen(endptr)!=0 || opcion_l < 1 || opcion_l > i) { printf("Ops... tendrás que meter un número entre 1 y %d la próxima vez ;) Try again!\n", i); fflush(stdout); valido=1; } }while(valido==1); /*Guardamos el nombre del archivo correspondiente en rutaKeyset*/ dir = opendir ("./Firmas digitales/"); i=0; while ((ent = readdir (dir)) != NULL) { if((ptr=strstr(ent->d_name, ".p7s"))!=NULL) { i++; if(opcion_l==i) { sprintf(rutaFirma, "./Firmas digitales/%s", ent->d_name); } } } closedir(dir); } else if(i==1) { printf("\n-> Se ha encontrado 1 firma adecuada. Se usará la firma %s por defecto\n\n", nombreFirma); fflush(stdout); sprintf(rutaFirma, "./Firmas digitales/%s", nombreFirma); } /*Abrimos la firma*/ if((ptrFirma=fopen(rutaFirma, "rb")) < 0) { printf("Error al crear el archivo\n"); fflush(stdout); return(-1); } stat(rutaFirma, &st); tamFirma=st.st_size; firma=(char *)malloc(tamFirma); fread(firma, 1, tamFirma, ptrFirma); /*Ahora necesitamos el certificado*/ dir = opendir ("./Claves y certificados/"); if (dir != NULL) { i=0; /* Nos va a mostrar los archivos que haya dentro de la carpeta Claves y cert.*/ while ((ent = readdir (dir)) != NULL) { if((ptr=strstr(ent->d_name, ".cert"))!=NULL) { strcpy(nombreCert, ent->d_name); i++; } } closedir(dir); } else { /* Problemas al abrir el directorio */ printf("¿Ha ejecutado ya la opción 1?\n"); fflush(stdout); return(-1); } if(i==0) { printf("No se ha encontrado ningún certificado. (¿Ha ejecutado ya la opción 1?)\n"); fflush(stdout); return(-1); } else if(i==1) { printf("\n-> Se ha encontrado 1 certificado. Se usará el certificado %s por defecto\n\n", nombreCert); fflush(stdout); sprintf(rutaCert, "./Claves y certificados/%s", nombreCert); } else { printf("\n¡¡Hay %d certificados creados !!\n", i); fflush(stdout); i=0; dir = opendir ("./Claves y certificados/"); /* Nos va a mostrar los archivos que haya dentro de la carpeta Claves y cert.*/ while ((ent = readdir (dir)) != NULL) { if((ptr=strstr(ent->d_name, ".cert"))!=NULL) { i++; printf(" %d. %s\n", i, ent->d_name); } } closedir(dir); do{ valido=0; printf("Introduzca el número del certificado que desea usar >> "); scanf("%s", &opcion); opcion_l = strtol(opcion,&endptr,10); if(strlen(endptr)!=0 || opcion_l < 1 || opcion_l > i) { printf("Ops... tendrás que meter un número entre 1 y %d la próxima vez ;) Try again!\n", i); fflush(stdout); valido=1; } }while(valido==1); /*Guardamos el nombre del archivo correspondiente en rutaCert*/ dir = opendir ("./Claves y certificados/"); i=0; while ((ent = readdir (dir)) != NULL) { if((ptr=strstr(ent->d_name, ".cert"))!=NULL) { i++; if(opcion_l==i) { sprintf(rutaCert, "./Claves y certificados/%s", ent->d_name); } } } closedir(dir); } ptrCert=fopen(rutaCert, "rb"); stat(rutaCert, &st); tamCert=st.st_size; cert=(char *)malloc(tamCert); fread(cert, 1, tamCert, ptrCert); /*Importamos certificado*/ /*Creo el contexto para el hash*/ CRYPT_CONTEXT contextoHash; if((status=cryptCreateContext(&contextoHash, CRYPT_UNUSED, CRYPT_ALGO_SHA1))!=CRYPT_OK) { printf("Error al crear el contexto. Código %d\n", status); fflush(stdout); return(-1); } /*Hash*/ if((status=cryptEncrypt(contextoHash, buffer, tam))!=CRYPT_OK) { printf("Error al calcular el hash. Código %d\n", status); fflush(stdout); return(-1); } if((status=cryptEncrypt(contextoHash, buffer, 0))!=CRYPT_OK) { printf("Error al calcular el hash. Código %d\n", status); fflush(stdout); return(-1); } CRYPT_CERTIFICATE certificado; if((status=cryptImportCert(cert, tamCert, CRYPT_UNUSED, &certificado))!=CRYPT_OK) { printf("Error al importar el certificado. Código %d\n", status); fflush(stdout); return(-1); } if((status=cryptCheckSignature(firma, tamFirma, certificado, contextoHash))!=CRYPT_OK) { printf("La firma no concuerda. Código %d\n", status); fflush(stdout); return(-1); } /*Destruimos contextos y cerramos lo necesario*/ if((status=cryptDestroyContext(contextoHash))!=CRYPT_OK) { printf("Error al destruir el contexto. Código %d\n", status); fflush(stdout); return(-1); } if((status=cryptDestroyCert(certificado))!=CRYPT_OK) { printf("Error al destruir el certificado. Código %d\n", status); fflush(stdout); return(-1); } return(0); }