Esempio n. 1
0
SECStatus
SGN_End(SGNContext *cx, SECItem *result)
{
    unsigned char digest[HASH_LENGTH_MAX];
    unsigned part1;
    int signatureLen;
    SECStatus rv;
    SECItem digder, sigitem;
    PLArenaPool *arena = 0;
    SECKEYPrivateKey *privKey = cx->key;
    SGNDigestInfo *di = 0;

    result->data = 0;
    digder.data = 0;

    /* Finish up digest function */
    if (cx->hashcx == NULL) {
	PORT_SetError(SEC_ERROR_INVALID_ARGS);
	return SECFailure;
    }
    (*cx->hashobj->end)(cx->hashcx, digest, &part1, sizeof(digest));


    if (privKey->keyType == rsaKey) {

	arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
	if ( !arena ) {
	    rv = SECFailure;
	    goto loser;
	}
    
	/* Construct digest info */
	di = SGN_CreateDigestInfo(cx->hashalg, digest, part1);
	if (!di) {
	    rv = SECFailure;
	    goto loser;
	}

	/* Der encode the digest as a DigestInfo */
        rv = DER_Encode(arena, &digder, SGNDigestInfoTemplate,
                        di);
	if (rv != SECSuccess) {
	    goto loser;
	}
    } else {
	digder.data = digest;
	digder.len = part1;
    }

    /*
    ** Encrypt signature after constructing appropriate PKCS#1 signature
    ** block
    */
    signatureLen = PK11_SignatureLen(privKey);
    if (signatureLen <= 0) {
	PORT_SetError(SEC_ERROR_INVALID_KEY);
	rv = SECFailure;
	goto loser;
    }
    sigitem.len = signatureLen;
    sigitem.data = (unsigned char*) PORT_Alloc(signatureLen);

    if (sigitem.data == NULL) {
	rv = SECFailure;
	goto loser;
    }

    rv = PK11_Sign(privKey, &sigitem, &digder);
    if (rv != SECSuccess) {
	PORT_Free(sigitem.data);
	sigitem.data = NULL;
	goto loser;
    }

    if ((cx->signalg == SEC_OID_ANSIX9_DSA_SIGNATURE) ||
        (cx->signalg == SEC_OID_ANSIX962_EC_PUBLIC_KEY)) {
        /* DSAU_EncodeDerSigWithLen works for DSA and ECDSA */
	rv = DSAU_EncodeDerSigWithLen(result, &sigitem, sigitem.len); 
	PORT_Free(sigitem.data);
	if (rv != SECSuccess)
	    goto loser;
    } else {
	result->len = sigitem.len;
	result->data = sigitem.data;
    }

  loser:
    SGN_DestroyDigestInfo(di);
    if (arena != NULL) {
	PORT_FreeArena(arena, PR_FALSE);
    }
    return rv;
}
Esempio n. 2
0
SECStatus
SGN_Digest(SECKEYPrivateKey *privKey,
		SECOidTag algtag, SECItem *result, SECItem *digest)
{
    int modulusLen;
    SECStatus rv;
    SECItem digder;
    PLArenaPool *arena = 0;
    SGNDigestInfo *di = 0;


    result->data = 0;

    if (privKey->keyType == rsaKey) {

	arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
	if ( !arena ) {
	    rv = SECFailure;
	    goto loser;
	}
    
	/* Construct digest info */
	di = SGN_CreateDigestInfo(algtag, digest->data, digest->len);
	if (!di) {
	    rv = SECFailure;
	    goto loser;
	}

	/* Der encode the digest as a DigestInfo */
        rv = DER_Encode(arena, &digder, SGNDigestInfoTemplate,
                        di);
	if (rv != SECSuccess) {
	    goto loser;
	}
    } else {
	digder.data = digest->data;
	digder.len = digest->len;
    }

    /*
    ** Encrypt signature after constructing appropriate PKCS#1 signature
    ** block
    */
    modulusLen = PK11_SignatureLen(privKey);
    if (modulusLen <= 0) {
	PORT_SetError(SEC_ERROR_INVALID_KEY);
	rv = SECFailure;
	goto loser;
    }
    result->len = modulusLen;
    result->data = (unsigned char*) PORT_Alloc(modulusLen);
    result->type = siBuffer;

    if (result->data == NULL) {
	rv = SECFailure;
	goto loser;
    }

    rv = PK11_Sign(privKey, result, &digder);
    if (rv != SECSuccess) {
	PORT_Free(result->data);
	result->data = NULL;
    }

  loser:
    SGN_DestroyDigestInfo(di);
    if (arena != NULL) {
	PORT_FreeArena(arena, PR_FALSE);
    }
    return rv;
}
Esempio n. 3
0
SGNDigestInfo *
SGN_CreateDigestInfo(SECOidTag algorithm, const unsigned char *sig,
                     unsigned len)
{
    SGNDigestInfo *di;
    SECStatus rv;
    PLArenaPool *arena;
    SECItem *null_param;
    SECItem dummy_value;

    switch (algorithm) {
    case SEC_OID_MD2:
    case SEC_OID_MD5:
    case SEC_OID_SHA1:
    case SEC_OID_SHA224:
    case SEC_OID_SHA256:
    case SEC_OID_SHA384:
    case SEC_OID_SHA512:
        break;
    default:
        PORT_SetError(SEC_ERROR_INVALID_ALGORITHM);
        return NULL;
    }

    arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
    if (arena == NULL) {
        return NULL;
    }

    di = (SGNDigestInfo *) PORT_ArenaZAlloc(arena, sizeof(SGNDigestInfo));
    if (di == NULL) {
        PORT_FreeArena(arena, PR_FALSE);
        return NULL;
    }

    di->arena = arena;

    /*
     * PKCS #1 specifies that the AlgorithmID must have a NULL parameter
     * (as opposed to no parameter at all).
     */
    dummy_value.data = NULL;
    dummy_value.len = 0;
    null_param = SEC_ASN1EncodeItem(NULL, NULL, &dummy_value, SEC_NullTemplate);
    if (null_param == NULL) {
        goto loser;
    }

    rv = SECOID_SetAlgorithmID(arena, &di->digestAlgorithm, algorithm,
                               null_param);

    SECITEM_FreeItem(null_param, PR_TRUE);

    if (rv != SECSuccess) {
        goto loser;
    }

    di->digest.data = (unsigned char *) PORT_ArenaAlloc(arena, len);
    if (di->digest.data == NULL) {
        goto loser;
    }

    di->digest.len = len;
    PORT_Memcpy(di->digest.data, sig, len);
    return di;

loser:
    SGN_DestroyDigestInfo(di);
    return NULL;
}
Esempio n. 4
0
SECStatus
SGN_End(SGNContext *cx, SECItem *result)
{
    unsigned char digest[HASH_LENGTH_MAX];
    unsigned part1;
    int signatureLen;
    SECStatus rv;
    SECItem digder, sigitem;
    PLArenaPool *arena = 0;
    SECKEYPrivateKey *privKey = cx->key;
    SGNDigestInfo *di = 0;

    result->data = 0;
    digder.data = 0;
    sigitem.data = 0;

    /* Finish up digest function */
    if (cx->hashcx == NULL) {
        PORT_SetError(SEC_ERROR_INVALID_ARGS);
        return SECFailure;
    }
    (*cx->hashobj->end)(cx->hashcx, digest, &part1, sizeof(digest));

    if (privKey->keyType == rsaKey &&
        cx->signalg != SEC_OID_PKCS1_RSA_PSS_SIGNATURE) {

        arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
        if (!arena) {
            rv = SECFailure;
            goto loser;
        }

        /* Construct digest info */
        di = SGN_CreateDigestInfo(cx->hashalg, digest, part1);
        if (!di) {
            rv = SECFailure;
            goto loser;
        }

        /* Der encode the digest as a DigestInfo */
        rv = DER_Encode(arena, &digder, SGNDigestInfoTemplate,
                        di);
        if (rv != SECSuccess) {
            goto loser;
        }
    } else {
        digder.data = digest;
        digder.len = part1;
    }

    /*
    ** Encrypt signature after constructing appropriate PKCS#1 signature
    ** block
    */
    signatureLen = PK11_SignatureLen(privKey);
    if (signatureLen <= 0) {
        PORT_SetError(SEC_ERROR_INVALID_KEY);
        rv = SECFailure;
        goto loser;
    }
    sigitem.len = signatureLen;
    sigitem.data = (unsigned char *)PORT_Alloc(signatureLen);

    if (sigitem.data == NULL) {
        rv = SECFailure;
        goto loser;
    }

    if (cx->signalg == SEC_OID_PKCS1_RSA_PSS_SIGNATURE) {
        CK_RSA_PKCS_PSS_PARAMS mech;
        SECItem mechItem = { siBuffer, (unsigned char *)&mech, sizeof(mech) };

        PORT_Memset(&mech, 0, sizeof(mech));

        if (cx->params && cx->params->data) {
            SECKEYRSAPSSParams params;

            arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
            if (!arena) {
                rv = SECFailure;
                goto loser;
            }

            PORT_Memset(&params, 0, sizeof(params));
            rv = SEC_QuickDERDecodeItem(arena, &params,
                                        SECKEY_RSAPSSParamsTemplate,
                                        cx->params);
            if (rv != SECSuccess) {
                goto loser;
            }
            rv = sec_RSAPSSParamsToMechanism(&mech, &params);
            if (rv != SECSuccess) {
                goto loser;
            }
        } else {
            mech.hashAlg = CKM_SHA_1;
            mech.mgf = CKG_MGF1_SHA1;
            mech.sLen = digder.len;
        }
        rv = PK11_SignWithMechanism(privKey, CKM_RSA_PKCS_PSS, &mechItem,
                                    &sigitem, &digder);
        if (rv != SECSuccess) {
            goto loser;
        }
    } else {
        rv = PK11_Sign(privKey, &sigitem, &digder);
        if (rv != SECSuccess) {
            goto loser;
        }
    }

    if ((cx->signalg == SEC_OID_ANSIX9_DSA_SIGNATURE) ||
        (cx->signalg == SEC_OID_ANSIX962_EC_PUBLIC_KEY)) {
        /* DSAU_EncodeDerSigWithLen works for DSA and ECDSA */
        rv = DSAU_EncodeDerSigWithLen(result, &sigitem, sigitem.len);
        if (rv != SECSuccess)
            goto loser;
        SECITEM_FreeItem(&sigitem, PR_FALSE);
    } else {
        result->len = sigitem.len;
        result->data = sigitem.data;
    }

loser:
    if (rv != SECSuccess) {
        SECITEM_FreeItem(&sigitem, PR_FALSE);
    }
    SGN_DestroyDigestInfo(di);
    if (arena != NULL) {
        PORT_FreeArena(arena, PR_FALSE);
    }
    return rv;
}
Esempio n. 5
0
unsigned int NSSCryptoKeyRSA::signSHA1PKCS1Base64Signature(unsigned char * hashBuf,
		unsigned int hashLen,
		char * base64SignatureBuf,
		unsigned int base64SignatureBufLen,
		hashMethod hm) {

	// Sign a pre-calculated hash using this key

	if (mp_privkey == 0) {
		
		throw XSECCryptoException(XSECCryptoException::RSAError,
			"NSS:RSA - Attempt to sign data using a public or un-loaded key");
		
	}
	
	unsigned char * rawSig;
	XSECnew(rawSig, unsigned char[base64SignatureBufLen]);
	ArrayJanitor<unsigned char> j_rawSig(rawSig);
	
	SECItem signature;
	signature.type = siBuffer;
	signature.data = rawSig;
	signature.len = base64SignatureBufLen;
	
	SECItem data;
	data.data = 0;
	SECOidTag hashalg;
	PRArenaPool * arena = 0;
	SGNDigestInfo *di = 0;
	SECItem * res;

	switch (hm) {

	case (HASH_MD5):
		hashalg = SEC_OID_MD5;
		break;
	case (HASH_SHA1):
		hashalg = SEC_OID_SHA1;
		break;
	case (HASH_SHA256):
		hashalg = SEC_OID_SHA256;
		break;
	case (HASH_SHA384):
		hashalg = SEC_OID_SHA384;
		break;
	case (HASH_SHA512):
		hashalg = SEC_OID_SHA512;
		break;
	default:
		throw XSECCryptoException(XSECCryptoException::RSAError,
			"NSS:RSA - Unsupported hash algorithm in RSA sign");
	}

	arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
	if (!arena) {
		throw XSECCryptoException(XSECCryptoException::RSAError,
			"NSS:RSA - Error creating arena");
	}

	di = SGN_CreateDigestInfo(hashalg, hashBuf, hashLen);	
	if (di == NULL) {
		
		PORT_FreeArena(arena, PR_FALSE);

		throw XSECCryptoException(XSECCryptoException::RSAError,
			"NSS:RSA - Error creating digest info");
	}

	res = SEC_ASN1EncodeItem(arena, &data, di, NSS_Get_sgn_DigestInfoTemplate(NULL, 0));

	if (!res) {
		SGN_DestroyDigestInfo(di);
		PORT_FreeArena(arena, PR_FALSE);

		throw XSECCryptoException(XSECCryptoException::RSAError,
			"NSS:RSA - Error encoding digest info for RSA sign");
	}

/*	data.type = siBuffer;
	data.data = hashBuf;
	data.len = hashLen;*/

	/* As of V1.3.1 - create a DigestInfo block */

	
	SECStatus s = PK11_Sign(mp_privkey, &signature, &data);
	
	SGN_DestroyDigestInfo(di);
	PORT_FreeArena(arena, PR_FALSE);

	if (s != SECSuccess) {
		
		throw XSECCryptoException(XSECCryptoException::RSAError,
			"NSS:RSA - Error during signing operation");
		
	}
	
	// Now encode
	XSCryptCryptoBase64 b64;
	b64.encodeInit();
	unsigned int ret = b64.encode(signature.data, signature.len, (unsigned char *) base64SignatureBuf, base64SignatureBufLen);
	ret += b64.encodeFinish((unsigned char *) &base64SignatureBuf[ret], base64SignatureBufLen - ret);
	
	return ret;
	
}
Esempio n. 6
0
bool NSSCryptoKeyRSA::verifySHA1PKCS1Base64Signature(const unsigned char * hashBuf, 
								 unsigned int hashLen,
								 const char * base64Signature,
								 unsigned int sigLen,
								 hashMethod hm) {

	// Use the currently loaded key to validate the Base64 encoded signature

	if (mp_pubkey == 0) {

      // Try to import from the parameters
		  importKey();

      if (mp_pubkey == 0) {

			    throw XSECCryptoException(XSECCryptoException::RSAError,
				      "NSS:RSA - Attempt to validate signature with empty key");

      }

	}

	// Decode the signature
	unsigned char * rawSig;
	unsigned int rawSigLen;
	XSECnew(rawSig, unsigned char[sigLen]);
	ArrayJanitor<unsigned char> j_rawSig(rawSig);

	// Decode the signature
	XSCryptCryptoBase64 b64;

	b64.decodeInit();
	rawSigLen = b64.decode((unsigned char *) base64Signature, sigLen, rawSig, sigLen);
	rawSigLen += b64.decodeFinish(&rawSig[rawSigLen], sigLen - rawSigLen);
	
  SECItem signature;
  signature.type = siBuffer;
  signature.data = rawSig;
  signature.len = rawSigLen;

  SECItem data; 
  data.data = 0;
  data.len = 0;
  SECOidTag hashalg;
  PRArenaPool * arena = 0;
  SGNDigestInfo *di = 0;
  SECItem * res;

  switch (hm) {

  case (HASH_MD5):
      hashalg = SEC_OID_MD5;
      break;
  case (HASH_SHA1):
      hashalg = SEC_OID_SHA1;
      break;
  case (HASH_SHA256):
      hashalg = SEC_OID_SHA256;
      break;
  case (HASH_SHA384):
      hashalg = SEC_OID_SHA384;
      break;
  case (HASH_SHA512):
      hashalg = SEC_OID_SHA512;
      break;
  default:
      throw XSECCryptoException(XSECCryptoException::RSAError,
          "NSS:RSA - Unsupported hash algorithm in RSA sign");
  }

  arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
  if (!arena) {
      throw XSECCryptoException(XSECCryptoException::RSAError,
          "NSS:RSA - Error creating arena");
  }

  di = SGN_CreateDigestInfo(hashalg, (unsigned char * )hashBuf, hashLen);
  if (di == NULL) {

      PORT_FreeArena(arena, PR_FALSE);

      throw XSECCryptoException(XSECCryptoException::RSAError,
          "NSS:RSA - Error creating digest info");
  }

  res = SEC_ASN1EncodeItem(arena, &data, di, NSS_Get_sgn_DigestInfoTemplate(NULL, 0));

  if (!res) {
      SGN_DestroyDigestInfo(di);
      PORT_FreeArena(arena, PR_FALSE);

      throw XSECCryptoException(XSECCryptoException::RSAError,
          "NSS:RSA - Error encoding digest info for RSA sign");
  }

	// Verify signature
	SECStatus s = PK11_Verify(mp_pubkey, &signature, &data, NULL);

  return s == SECSuccess;

}
Esempio n. 7
0
/* search a certificate list for a nickname, a thumbprint, or both
 * within a certificate bag.  if the certificate could not be
 * found or an error occurs, NULL is returned;
 */
static SEC_PKCS12CertAndCRL *
sec_pkcs12_find_cert_in_certbag(SEC_PKCS12CertAndCRLBag *certbag,
				SECItem *nickname, SGNDigestInfo *thumbprint)
{
    PRBool search_both = PR_FALSE, search_nickname = PR_FALSE;
    int i, j;

    if((certbag == NULL) || ((nickname == NULL) && (thumbprint == NULL))) {
	return NULL;
    }

    if(thumbprint && nickname) {
	search_both = PR_TRUE;
    }

    if(nickname) {
	search_nickname = PR_TRUE;
    }

search_again:  
    i = 0;
    while(certbag->certAndCRLs[i] != NULL) {
	SEC_PKCS12CertAndCRL *cert = certbag->certAndCRLs[i];

	if(SECOID_FindOIDTag(&cert->BagID) == SEC_OID_PKCS12_X509_CERT_CRL_BAG) {

	    /* check nicknames */
	    if(search_nickname) {
		if(SECITEM_CompareItem(nickname, &cert->nickname) == SECEqual) {
		    return cert;
		}
	    } else {
	    /* check thumbprints */
		SECItem **derCertList;

		/* get pointer to certificate list, does not need to
		 * be freed since it is within the arena which will
		 * be freed later.
		 */
		derCertList = SEC_PKCS7GetCertificateList(&cert->value.x509->certOrCRL);
		j = 0;
		if(derCertList != NULL) {
		    while(derCertList[j] != NULL) {
			SECComparison eq;
			SGNDigestInfo *di;
			di = sec_pkcs12_compute_thumbprint(derCertList[j]);
			if(di) {
			    eq = SGN_CompareDigestInfo(thumbprint, di);
			    SGN_DestroyDigestInfo(di);
			    if(eq == SECEqual) {
				/* copy the derCert for later reference */
				cert->value.x509->derLeafCert = derCertList[j];
				return cert;
			    }
			} else {
			    /* an error occurred */
			    return NULL;
			}
			j++;
		    }
		}
	    }
	}

	i++;
    }

    if(search_both) {
	search_both = PR_FALSE;
	search_nickname = PR_FALSE;
	goto search_again;
    }

    return NULL;
}