Beispiel #1
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;
}
Beispiel #2
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;
}
Beispiel #3
0
/* RSA sign/decrypt with the key, signature happens 'in place' */
vcard_7816_status_t
vcard_emul_rsa_op(VCard *card, VCardKey *key,
                  unsigned char *buffer, int buffer_size)
{
    SECKEYPrivateKey *priv_key;
    unsigned signature_len;
    PK11SlotInfo *slot;
    SECStatus rv;
    unsigned char buf[2048];
    unsigned char *bp = NULL;
    int pad_len;
    vcard_7816_status_t ret = VCARD7816_STATUS_SUCCESS;

    if ((!nss_emul_init) || (key == NULL)) {
        /* couldn't get the key, indicate that we aren't logged in */
        return VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED;
    }
    priv_key = vcard_emul_get_nss_key(key);
    if (priv_key == NULL) {
        /* couldn't get the key, indicate that we aren't logged in */
        return VCARD7816_STATUS_ERROR_CONDITION_NOT_SATISFIED;
    }
    slot = vcard_emul_card_get_slot(card);

    /*
     * this is only true of the rsa signature
     */
    signature_len = PK11_SignatureLen(priv_key);
    if (buffer_size != signature_len) {
        return  VCARD7816_STATUS_ERROR_DATA_INVALID;
    }
    /* be able to handle larger keys if necessariy */
    bp = &buf[0];
    if (sizeof(buf) < signature_len) {
        bp = g_malloc(signature_len);
    }

    /*
     * do the raw operations. Some tokens claim to do CKM_RSA_X_509, but then
     * choke when they try to do the actual operations. Try to detect
     * those cases and treat them as if the token didn't claim support for
     * X_509.
     */
    if (key->failedX509 != VCardEmulTrue
                              && PK11_DoesMechanism(slot, CKM_RSA_X_509)) {
        rv = PK11_PrivDecryptRaw(priv_key, bp, &signature_len, signature_len,
                                 buffer, buffer_size);
        if (rv == SECSuccess) {
            assert(buffer_size == signature_len);
            memcpy(buffer, bp, signature_len);
            key->failedX509 = VCardEmulFalse;
            goto cleanup;
        }
        /*
         * we've had a successful X509 operation, this failure must be
         * somethine else
         */
        if (key->failedX509 == VCardEmulFalse) {
            ret = vcard_emul_map_error(PORT_GetError());
            goto cleanup;
        }
        /*
         * key->failedX509 must be Unknown at this point, try the
         * non-x_509 case
         */
    }
    /* token does not support CKM_RSA_X509, emulate that with CKM_RSA_PKCS */
    /* is this a PKCS #1 formatted signature? */
    if ((buffer[0] == 0) && (buffer[1] == 1)) {
        int i;

        for (i = 2; i < buffer_size; i++) {
            /* rsa signature pad */
            if (buffer[i] != 0xff) {
                break;
            }
        }
        if ((i < buffer_size) && (buffer[i] == 0)) {
            /* yes, we have a properly formated PKCS #1 signature */
            /*
             * NOTE: even if we accidentally got an encrypt buffer, which
             * through shear luck started with 00, 01, ff, 00, it won't matter
             * because the resulting Sign operation will effectively decrypt
             * the real buffer.
             */
            SECItem signature;
            SECItem hash;

            i++;
            hash.data = &buffer[i];
            hash.len = buffer_size - i;
            signature.data = bp;
            signature.len = signature_len;
            rv = PK11_Sign(priv_key,  &signature, &hash);
            if (rv != SECSuccess) {
                ret = vcard_emul_map_error(PORT_GetError());
                goto cleanup;
            }
            assert(buffer_size == signature.len);
            memcpy(buffer, bp, signature.len);
            /*
             * we got here because either the X509 attempt failed, or the
             * token couldn't do the X509 operation, in either case stay
             * with the PKCS version for future operations on this key
             */
            key->failedX509 = VCardEmulTrue;
            goto cleanup;
        }
    }
    pad_len = buffer_size - signature_len;
    assert(pad_len < 4);
    /*
     * OK now we've decrypted the payload, package it up in PKCS #1 for the
     * upper layer.
     */
    buffer[0] = 0;
    buffer[1] = 2; /* RSA_encrypt  */
    pad_len -= 3; /* format is 0 || 2 || pad || 0 || data */
    /*
     * padding for PKCS #1 encrypted data is a string of random bytes. The
     * random butes protect against potential decryption attacks against RSA.
     * Since PrivDecrypt has already stripped those bytes, we can't reconstruct
     * them. This shouldn't matter to the upper level code which should just
     * strip this code out anyway, so We'll pad with a constant 3.
     */
    memset(&buffer[2], 0x03, pad_len);
    pad_len += 2; /* index to the end of the pad */
    buffer[pad_len] = 0;
    pad_len++; /* index to the start of the data */
    memcpy(&buffer[pad_len], bp, signature_len);
    /*
     * we got here because either the X509 attempt failed, or the
     * token couldn't do the X509 operation, in either case stay
     * with the PKCS version for future operations on this key
     */
    key->failedX509 = VCardEmulTrue;
cleanup:
    if (bp != buf) {
        g_free(bp);
    }
    return ret;
}
Beispiel #4
0
int sign_hash(const struct RSA_private_key *k
              , const u_char *hash_val, size_t hash_len
              , u_char *sig_val, size_t sig_len)
{
    SECKEYPrivateKey *privateKey = NULL;
    SECItem signature;
    SECItem data;
    SECItem ckaId;
    PK11SlotInfo *slot = NULL;

    DBG(DBG_CRYPT, DBG_log("RSA_sign_hash: Started using NSS"));

    ckaId.type=siBuffer;
    ckaId.len = k->ckaid_len;
    ckaId.data = DISCARD_CONST(unsigned char *, k->ckaid);

    slot = PK11_GetInternalKeySlot();
    if (slot == NULL) {
	loglog(RC_LOG_SERIOUS, "RSA_sign_hash: Unable to find (slot security) device (err %d)\n", PR_GetError());
	return 0;
    }

    if( PK11_Authenticate(slot, PR_FALSE,osw_return_nss_password_file_info()) == SECSuccess ) {
	DBG(DBG_CRYPT, DBG_log("NSS: Authentication to NSS successful\n"));
    }
    else {
	DBG(DBG_CRYPT, DBG_log("NSS: Authentication to NSS either failed or not required,if NSS DB without password\n"));
    }

    privateKey = PK11_FindKeyByKeyID(slot, &ckaId, osw_return_nss_password_file_info());
    if(privateKey==NULL) {
        DBG(DBG_CRYPT,
            DBG_log("Can't find the private key from the NSS CKA_ID"));
	if(k->pub.nssCert != NULL) {
	   privateKey = PK11_FindKeyByAnyCert(k->pub.nssCert,  osw_return_nss_password_file_info());
           if (privateKey == NULL) {
               loglog(RC_LOG_SERIOUS,
                      "Can't find the private key from the NSS CERT (err %d)",
                      PR_GetError());
           }
	}
    }

    PK11_FreeSlot(slot);

    if (privateKey == NULL) {
	loglog(RC_LOG_SERIOUS, "Can't find the private key from the NSS CERT (err %d)\n", PR_GetError());
	return 0;
    }

    data.type=siBuffer;
    data.len=hash_len;
    data.data = DISCARD_CONST(u_char *, hash_val);

    /*signature.len=PK11_SignatureLen(privateKey);*/
    signature.len=sig_len;
    signature.data=sig_val;

    {
        SECStatus s = PK11_Sign(privateKey, &signature, &data);

        if (s != SECSuccess) {
            loglog(RC_LOG_SERIOUS,
                   "RSA_sign_hash: sign function failed (%d)",
                   PR_GetError());
            return 0;
        }
    }

    DBG(DBG_CRYPT, DBG_log("RSA_sign_hash: Ended using NSS"));
    return signature.len;
}
Beispiel #5
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;
}
Beispiel #6
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;
	
}