Example #1
0
int oauth_verify_rsa_sha1 (const char *m, const char *c, const char *sig) {
  PK11SlotInfo      *slot = NULL;
  SECKEYPublicKey   *pkey = NULL;
  CERTCertificate   *cert = NULL;
  SECItem            signature;
  SECStatus          s;
  SECItem            der;
  int                rv=0;

  char *key = oauth_strip_pkcs(c, NS_CERT_HEADER, NS_CERT_TRAILER); 
  if (!key) return 0;

  oauth_init_nss();

  s = ATOB_ConvertAsciiToItem(&signature, (char*) sig); // XXX cast (const char*) -> (char*)
  if (s != SECSuccess) goto looser;
  slot = PK11_GetInternalKeySlot();
  if (!slot) goto looser;
  s = ATOB_ConvertAsciiToItem(&der, key);
  if (s != SECSuccess) goto looser;
  cert = __CERT_DecodeDERCertificate(&der, PR_TRUE, NULL);
  SECITEM_FreeItem(&der, PR_FALSE); 
  if (!cert) goto looser;
  pkey = CERT_ExtractPublicKey(cert);
  if (!pkey) goto looser;
  if (pkey->keyType != rsaKey) goto looser;

  s = VFY_VerifyData((unsigned char*) m, strlen(m), pkey, &signature, SEC_OID_ISO_SHA1_WITH_RSA_SIGNATURE, NULL);
  if (s == SECSuccess) rv=1;
#if 0
  else if (PR_GetError()!= SEC_ERROR_BAD_SIGNATURE) rv=-1;
#endif

looser:
  if (pkey) SECKEY_DestroyPublicKey(pkey);
  if (slot) PK11_FreeSlot(slot);
  free(key);
  return rv;
}
Example #2
0
OSStatus
SecCmsSignerInfoVerifyWithPolicy(SecCmsSignerInfoRef signerinfo,CFTypeRef timeStampPolicy, CSSM_DATA_PTR digest, CSSM_DATA_PTR contentType)
{
    SecPublicKeyRef publickey = NULL;
    SecCmsAttribute *attr;
    CSSM_DATA encoded_attrs;
    SecCertificateRef cert;
    SecCmsVerificationStatus vs = SecCmsVSUnverified;
    PLArenaPool *poolp;
    SECOidTag digestAlgTag, digestEncAlgTag;
    
    if (signerinfo == NULL)
	return SECFailure;
    
    /* SecCmsSignerInfoGetSigningCertificate will fail if 2nd parm is NULL and */
    /* cert has not been verified */
    if ((cert = SecCmsSignerInfoGetSigningCertificate(signerinfo, NULL)) == NULL) {
	dprintf("SecCmsSignerInfoVerify: no signing cert\n");
	vs = SecCmsVSSigningCertNotFound;
	goto loser;
    }

    dprintfRC("SecCmsSignerInfoVerify top: cert %p cert.rc %d\n", cert, (int)CFGetRetainCount(cert));
    
    debugShowSigningCertificate(signerinfo);

    OSStatus status;
    if ((status = SecCertificateCopyPublicKey(cert, &publickey))) {
        syslog(LOG_ERR, "SecCmsSignerInfoVerifyWithPolicy: copy public key failed %d", (int)status);
	vs = SecCmsVSProcessingError;
	goto loser;
    }

    digestAlgTag = SECOID_GetAlgorithmTag(&(signerinfo->digestAlg));
    digestEncAlgTag = SECOID_GetAlgorithmTag(&(signerinfo->digestEncAlg));
    
    /*
     * Gross hack necessitated by RFC 3278 section 2.1.1, which states 
     * that the signature algorithm (here, digestEncAlg) contains ecdsa_with-SHA1, 
     * *not* (as in all other algorithms) the raw signature algorithm, e.g. 
     * pkcs1RSAEncryption.
     */
    if(digestEncAlgTag == SEC_OID_ECDSA_WithSHA1) {
	digestEncAlgTag = SEC_OID_EC_PUBLIC_KEY;
    }
    
    if (!SecCmsArrayIsEmpty((void **)signerinfo->authAttr)) {
	if (contentType) {
	    /*
	     * Check content type
	     *
	     * RFC2630 sez that if there are any authenticated attributes,
	     * then there must be one for content type which matches the
	     * content type of the content being signed, and there must
	     * be one for message digest which matches our message digest.
	     * So check these things first.
	     */
	    if ((attr = SecCmsAttributeArrayFindAttrByOidTag(signerinfo->authAttr,
					SEC_OID_PKCS9_CONTENT_TYPE, PR_TRUE)) == NULL)
	    {
		vs = SecCmsVSMalformedSignature;
		goto loser;
	    }
		
	    if (SecCmsAttributeCompareValue(attr, contentType) == PR_FALSE) {
		vs = SecCmsVSMalformedSignature;
		goto loser;
	    }
	}

	/*
	 * Check digest
	 */
	if ((attr = SecCmsAttributeArrayFindAttrByOidTag(signerinfo->authAttr, SEC_OID_PKCS9_MESSAGE_DIGEST, PR_TRUE)) == NULL)
	{
	    vs = SecCmsVSMalformedSignature;
	    goto loser;
	}
	if (SecCmsAttributeCompareValue(attr, digest) == PR_FALSE) {
	    vs = SecCmsVSDigestMismatch;
	    goto loser;
	}

	if ((poolp = PORT_NewArena (1024)) == NULL) {
	    vs = SecCmsVSProcessingError;
	    goto loser;
	}

	/*
	 * Check signature
	 *
	 * The signature is based on a digest of the DER-encoded authenticated
	 * attributes.  So, first we encode and then we digest/verify.
	 * we trust the decoder to have the attributes in the right (sorted) order
	 */
	encoded_attrs.Data = NULL;
	encoded_attrs.Length = 0;

	if (SecCmsAttributeArrayEncode(poolp, &(signerinfo->authAttr), &encoded_attrs) == NULL ||
		encoded_attrs.Data == NULL || encoded_attrs.Length == 0)
	{
	    vs = SecCmsVSProcessingError;
	    goto loser;
	}

	vs = (VFY_VerifyData (encoded_attrs.Data, (int)encoded_attrs.Length,
			publickey, &(signerinfo->encDigest),
			digestAlgTag, digestEncAlgTag,
			signerinfo->cmsg->pwfn_arg) != SECSuccess) ? SecCmsVSBadSignature : SecCmsVSGoodSignature;

        dprintf("VFY_VerifyData (authenticated attributes): %s\n",
            (vs == SecCmsVSGoodSignature)?"SecCmsVSGoodSignature":"SecCmsVSBadSignature");

	PORT_FreeArena(poolp, PR_FALSE);	/* awkward memory management :-( */

    } else {
	CSSM_DATA_PTR sig;

	/* No authenticated attributes. The signature is based on the plain message digest. */
	sig = &(signerinfo->encDigest);
	if (sig->Length == 0)
	    goto loser;

	vs = (VFY_VerifyDigest(digest, publickey, sig,
			digestAlgTag, digestEncAlgTag,
			signerinfo->cmsg->pwfn_arg) != SECSuccess) ? SecCmsVSBadSignature : SecCmsVSGoodSignature;

        dprintf("VFY_VerifyData (plain message digest): %s\n",
            (vs == SecCmsVSGoodSignature)?"SecCmsVSGoodSignature":"SecCmsVSBadSignature");
    }
    
    if (!SecCmsArrayIsEmpty((void **)signerinfo->unAuthAttr))
    {
        dprintf("found an unAuthAttr\n");
        OSStatus rux = SecCmsSignerInfoVerifyUnAuthAttrsWithPolicy(signerinfo,timeStampPolicy);
        dprintf("SecCmsSignerInfoVerifyUnAuthAttrs Status: %ld\n", (long)rux);
        if (rux) {
            goto loser;
        }
    }

    if (vs == SecCmsVSBadSignature) {
	/*
	 * XXX Change the generic error into our specific one, because
	 * in that case we get a better explanation out of the Security
	 * Advisor.  This is really a bug in our error strings (the
	 * "generic" error has a lousy/wrong message associated with it
	 * which assumes the signature verification was done for the
	 * purposes of checking the issuer signature on a certificate)
	 * but this is at least an easy workaround and/or in the
	 * Security Advisor, which specifically checks for the error
	 * SEC_ERROR_PKCS7_BAD_SIGNATURE and gives more explanation
	 * in that case but does not similarly check for
	 * SEC_ERROR_BAD_SIGNATURE.  It probably should, but then would
	 * probably say the wrong thing in the case that it *was* the
	 * certificate signature check that failed during the cert
	 * verification done above.  Our error handling is really a mess.
	 */
	if (PORT_GetError() == SEC_ERROR_BAD_SIGNATURE)
	    PORT_SetError(SEC_ERROR_PKCS7_BAD_SIGNATURE);
    }

    if (publickey != NULL)
	CFRelease(publickey);

    signerinfo->verificationStatus = vs;
    dprintfRC("SecCmsSignerInfoVerify end: cerp %p cert.rc %d\n",
	    cert, (int)CFGetRetainCount(cert));

    dprintf("verificationStatus: %d\n", vs);

    return (vs == SecCmsVSGoodSignature) ? SECSuccess : SECFailure;

loser:
    if (publickey != NULL)
	SECKEY_DestroyPublicKey (publickey);

    dprintf("verificationStatus2: %d\n", vs);
    signerinfo->verificationStatus = vs;

    PORT_SetError (SEC_ERROR_PKCS7_BAD_SIGNATURE);
    return SECFailure;
}