Example #1
0
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;
}
Example #2
0
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);

}