pk11skey.c
来自「支持SSL v2/v3, TLS, PKCS #5, PKCS #7, PKCS」· C语言 代码 · 共 2,251 行 · 第 1/5 页
C
2,251 行
privKey->pkcs11ID, CKA_DECRYPT ); /* If the encryption attribute is set; attempt to encrypt */ /* with the public key and decrypt with the private key. */ if( isEncryptable ) { /* Find a module to encrypt against */ slot = PK11_GetBestSlot(pk11_mapWrapKeyType(privKey->keyType),wincx); if (slot == NULL) { PORT_SetError( SEC_ERROR_NO_MODULE ); return SECFailure; } id = PK11_ImportPublicKey(slot,pubKey,PR_FALSE); if (id == CK_INVALID_KEY) { PK11_FreeSlot(slot); return SECFailure; } /* Compute max bytes encrypted from modulus length of private key. */ max_bytes_encrypted = PK11_GetPrivateModulusLen( privKey ); /* Prepare for encryption using the public key. */ PK11_EnterSlotMonitor(slot); crv = PK11_GETTAB( slot )->C_EncryptInit( slot->session, mech, id ); if( crv != CKR_OK ) { PK11_ExitSlotMonitor(slot); PORT_SetError( PK11_MapError( crv ) ); PK11_FreeSlot(slot); return SECFailure; } /* Allocate space for ciphertext. */ ciphertext = (unsigned char *) PORT_Alloc( max_bytes_encrypted ); if( ciphertext == NULL ) { PK11_ExitSlotMonitor(slot); PORT_SetError( SEC_ERROR_NO_MEMORY ); PK11_FreeSlot(slot); return SECFailure; } /* Initialize bytes encrypted to max bytes encrypted. */ bytes_encrypted = max_bytes_encrypted; /* Encrypt using the public key. */ crv = PK11_GETTAB( slot )->C_Encrypt( slot->session, known_message, PAIRWISE_MESSAGE_LENGTH, ciphertext, &bytes_encrypted ); PK11_ExitSlotMonitor(slot); PK11_FreeSlot(slot); if( crv != CKR_OK ) { PORT_SetError( PK11_MapError( crv ) ); PORT_Free( ciphertext ); return SECFailure; } /* Always use the smaller of these two values . . . */ bytes_compared = ( bytes_encrypted > PAIRWISE_MESSAGE_LENGTH ) ? PAIRWISE_MESSAGE_LENGTH : bytes_encrypted; /* If there was a failure, the plaintext */ /* goes at the end, therefore . . . */ text_compared = ( bytes_encrypted > PAIRWISE_MESSAGE_LENGTH ) ? (ciphertext + bytes_encrypted - PAIRWISE_MESSAGE_LENGTH ) : ciphertext; /* Check to ensure that ciphertext does */ /* NOT EQUAL known input message text */ /* per FIPS PUB 140-1 directive. */ if( ( bytes_encrypted != max_bytes_encrypted ) || ( PORT_Memcmp( text_compared, known_message, bytes_compared ) == 0 ) ) { /* Set error to Invalid PRIVATE Key. */ PORT_SetError( SEC_ERROR_INVALID_KEY ); PORT_Free( ciphertext ); return SECFailure; } slot = privKey->pkcs11Slot; /* Prepare for decryption using the private key. */ PK11_EnterSlotMonitor(slot); crv = PK11_GETTAB( slot )->C_DecryptInit( slot->session, mech, privKey->pkcs11ID ); if( crv != CKR_OK ) { PK11_ExitSlotMonitor(slot); PORT_SetError( PK11_MapError(crv) ); PORT_Free( ciphertext ); PK11_FreeSlot(slot); return SECFailure; } /* Initialize bytes decrypted to be the */ /* expected PAIRWISE_MESSAGE_LENGTH. */ bytes_decrypted = PAIRWISE_MESSAGE_LENGTH; /* Decrypt using the private key. */ /* NOTE: No need to reset the */ /* value of bytes_encrypted. */ crv = PK11_GETTAB( slot )->C_Decrypt( slot->session, ciphertext, bytes_encrypted, plaintext, &bytes_decrypted ); PK11_ExitSlotMonitor(slot); /* Finished with ciphertext; free it. */ PORT_Free( ciphertext ); if( crv != CKR_OK ) { PORT_SetError( PK11_MapError(crv) ); PK11_FreeSlot(slot); return SECFailure; } /* Check to ensure that the output plaintext */ /* does EQUAL known input message text. */ if( ( bytes_decrypted != PAIRWISE_MESSAGE_LENGTH ) || ( PORT_Memcmp( plaintext, known_message, PAIRWISE_MESSAGE_LENGTH ) != 0 ) ) { /* Set error to Bad PUBLIC Key. */ PORT_SetError( SEC_ERROR_BAD_KEY ); PK11_FreeSlot(slot); return SECFailure; } } /**********************************************/ /* Pairwise Consistency Check of Sign/Verify. */ /**********************************************/ canSignVerify = PK11_HasAttributeSet ( privKey->pkcs11Slot, privKey->pkcs11ID, CKA_VERIFY); if (canSignVerify) { /* Initialize signature and digest data. */ signature.data = NULL; digest.data = NULL; /* Determine length of signature. */ signature_length = PK11_SignatureLen( privKey ); if( signature_length == 0 ) goto failure; /* Allocate space for signature data. */ signature.data = (unsigned char *) PORT_Alloc( signature_length ); if( signature.data == NULL ) { PORT_SetError( SEC_ERROR_NO_MEMORY ); goto failure; } /* Allocate space for known digest data. */ digest.data = (unsigned char *) PORT_Alloc( PAIRWISE_DIGEST_LENGTH ); if( digest.data == NULL ) { PORT_SetError( SEC_ERROR_NO_MEMORY ); goto failure; } /* "Fill" signature type and length. */ signature.type = PAIRWISE_SECITEM_TYPE; signature.len = signature_length; /* "Fill" digest with known SHA-1 digest parameters. */ digest.type = PAIRWISE_SECITEM_TYPE; PORT_Memcpy( digest.data, known_digest, PAIRWISE_DIGEST_LENGTH ); digest.len = PAIRWISE_DIGEST_LENGTH; /* Sign the known hash using the private key. */ rv = PK11_Sign( privKey, &signature, &digest ); if( rv != SECSuccess ) goto failure; /* Verify the known hash using the public key. */ rv = PK11_Verify( pubKey, &signature, &digest, wincx ); if( rv != SECSuccess ) goto failure; /* Free signature and digest data. */ PORT_Free( signature.data ); PORT_Free( digest.data ); } /**********************************************/ /* Pairwise Consistency Check for Derivation */ /**********************************************/ isDerivable = PK11_HasAttributeSet ( privKey->pkcs11Slot, privKey->pkcs11ID, CKA_DERIVE); if (isDerivable) { /* * We are not doing consistency check for Diffie-Hellman Key - * otherwise it would be here */ } return SECSuccess;failure: if( signature.data != NULL ) PORT_Free( signature.data ); if( digest.data != NULL ) PORT_Free( digest.data ); return SECFailure;}/* * take a private key in one pkcs11 module and load it into another: * NOTE: the source private key is a rare animal... it can't be sensitive. * This is used to do a key gen using one pkcs11 module and storing the * result into another. */SECKEYPrivateKey *pk11_loadPrivKey(PK11SlotInfo *slot,SECKEYPrivateKey *privKey, SECKEYPublicKey *pubKey, PRBool token, PRBool sensitive) { CK_ATTRIBUTE privTemplate[] = { /* class must be first */ { CKA_CLASS, NULL, 0 }, { CKA_KEY_TYPE, NULL, 0 }, /* these three must be next */ { CKA_TOKEN, NULL, 0 }, { CKA_PRIVATE, NULL, 0 }, { CKA_SENSITIVE, NULL, 0 }, { CKA_ID, NULL, 0 },#ifdef notdef { CKA_LABEL, NULL, 0 }, { CKA_SUBJECT, NULL, 0 },#endif /* RSA */ { CKA_MODULUS, NULL, 0 }, { CKA_PRIVATE_EXPONENT, NULL, 0 }, { CKA_PUBLIC_EXPONENT, NULL, 0 }, { CKA_PRIME_1, NULL, 0 }, { CKA_PRIME_2, NULL, 0 }, { CKA_EXPONENT_1, NULL, 0 }, { CKA_EXPONENT_2, NULL, 0 }, { CKA_COEFFICIENT, NULL, 0 }, }; CK_ATTRIBUTE *attrs = NULL, *ap; int templateSize = sizeof(privTemplate)/sizeof(privTemplate[0]); PRArenaPool *arena; CK_OBJECT_HANDLE objectID; int i, count = 0; int extra_count = 0; CK_RV crv; SECStatus rv; for (i=0; i < templateSize; i++) { if (privTemplate[i].type == CKA_MODULUS) { attrs= &privTemplate[i]; count = i; break; } } PORT_Assert(attrs != NULL); if (attrs == NULL) { PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return NULL; } ap = attrs; switch (privKey->keyType) { case rsaKey: count = templateSize; extra_count = templateSize - (attrs - privTemplate); break; case dsaKey: ap->type = CKA_PRIME; ap++; count++; extra_count++; ap->type = CKA_SUBPRIME; ap++; count++; extra_count++; ap->type = CKA_BASE; ap++; count++; extra_count++; ap->type = CKA_VALUE; ap++; count++; extra_count++; break; case dhKey: ap->type = CKA_PRIME; ap++; count++; extra_count++; ap->type = CKA_BASE; ap++; count++; extra_count++; ap->type = CKA_VALUE; ap++; count++; extra_count++; break; default: count = 0; extra_count = 0; break; } if (count == 0) { PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); return NULL; } arena = PORT_NewArena( DER_DEFAULT_CHUNKSIZE); if (arena == NULL) return NULL; /* * read out the old attributes. */ crv = PK11_GetAttributes(arena, privKey->pkcs11Slot, privKey->pkcs11ID, privTemplate,count); if (crv != CKR_OK) { PORT_SetError( PK11_MapError(crv) ); PORT_FreeArena(arena, PR_TRUE); return NULL; } /* Reset sensitive, token, and private */ *(CK_BBOOL *)(privTemplate[2].pValue) = token ? CK_TRUE : CK_FALSE; *(CK_BBOOL *)(privTemplate[3].pValue) = token ? CK_TRUE : CK_FALSE; *(CK_BBOOL *)(privTemplate[4].pValue) = sensitive ? CK_TRUE : CK_FALSE; /* Not everyone can handle zero padded key values, give * them the raw data as unsigned */ for (ap=attrs; extra_count; ap++, extra_count--) { pk11_SignedToUnsigned(ap); } /* now Store the puppies */ rv = PK11_CreateNewObject(slot, CK_INVALID_SESSION, privTemplate, count, token, &objectID); PORT_FreeArena(arena, PR_TRUE); if (rv != SECSuccess) { return NULL; } /* try loading the public key as a token object */ if (pubKey) { PK11_ImportPublicKey(slot, pubKey, PR_TRUE); if (pubKey->pkcs11Slot) { PK11_FreeSlot(pubKey->pkcs11Slot); pubKey->pkcs11Slot = NULL; pubKey->pkcs11ID = CK_INVALID_KEY; } } /* build new key structure */ return PK11_MakePrivKey(slot, privKey->keyType, (PRBool)!token, objectID, privKey->wincx);}/* * Use the token to Generate a key. keySize must be 'zero' for fixed key * length algorithms. NOTE: this means we can never generate a DES2 key * from this interface! */SECKEYPrivateKey *PK11_GenerateKeyPair(PK11SlotInfo *slot,CK_MECHANISM_TYPE type, void *param, SECKEYPublicKey **pubKey, PRBool token, PRBool sensitive, void *wincx){ /* we have to use these native types because when we call PKCS 11 modules * we have to make sure that we are using the correct sizes for all the * parameters. */ CK_BBOOL ckfalse = CK_FALSE; CK_BBOOL cktrue = CK_TRUE; CK_ULONG modulusBits; CK_BYTE publicExponent[4]; CK_ATTRIBUTE privTemplate[] = { { CKA_SENSITIVE, NULL, 0}, { CKA_TOKEN, NULL, 0}, { CKA_PRIVATE, NULL, 0}, { CKA_DERIVE, NULL, 0}, { CKA_UNWRAP, NULL, 0}, { CKA_SIGN, NULL, 0}, { CKA_DECRYPT, NULL, 0}, }; CK_ATTRIBUTE rsaPubTemplate[] = { { CKA_MODULUS_BITS, NULL, 0}, { CKA_PUBLIC_EXPONENT, NULL, 0}, { CKA_TOKEN, NULL, 0}, { CKA_DERIVE, NULL, 0}, { CKA_WRAP, NULL, 0}, { CKA_VERIFY, NULL, 0}, { CKA_VERIFY_RECOVER, NULL, 0}, { CKA_ENCRYPT, NULL, 0}, }; CK_ATTRIBUTE dsaPubTemplate[] = { { CKA_PRIME, NULL, 0 }, { CKA_SUBPRIME, NULL, 0 }, { CKA_BASE, NULL, 0 }, { CKA_TOKEN, NULL, 0}, { CKA_DERIVE, NULL, 0}, { CKA_WRAP, NULL, 0}, { CKA_VERIFY, NULL, 0}, { CKA_VERIFY_RECOVER, NULL, 0}, { CKA_ENCRYPT, NULL, 0}, }; CK_ATTRIBUTE dhPubTemplate[] = { { CKA_PRIME, NULL, 0 }, { CKA_BASE, NULL, 0 }, { CKA_TOKEN, NULL, 0}, { CKA_DERIVE, NULL, 0}, { CKA_WRAP, NULL, 0}, { CKA_VERIFY, NULL, 0}, { CKA_VERIFY_RECOVER, NULL, 0}, { CKA_ENCRYPT, NULL, 0}, }; int dsaPubCount = sizeof(dsaPubTemplate)/sizeof(dsaPubTemplate[0]); /*CK_ULONG key_size = 0;*/ CK_ATTRIBUTE *pubTemplate; int privCount = sizeof(privTemplate)/sizeof(privTemplate[0]); int rsaPubCount = sizeof(rsaPubTemplate)/sizeof(rsaPubTemplate[0]); int dhPubCount = sizeof(dhPubTemplate)/sizeof(dhPubTemplate[0]); int pubCount = 0; PK11RSAGenParams *rsaParams; PQGParams *dsaParams; DHParams * dhParams; CK_MECHANISM mechanism; CK_MECHANISM test_mech; CK_SESSION_HANDLE session_handle; CK_RV crv; CK_OBJECT_HANDLE privID,pubID; SECKEYPrivateKey *privKey; KeyType keyType; PRBool restore; int peCount,i; CK_ATTRIBUTE *attrs; CK_ATTRIBUTE *privattrs; SECItem *pubKeyIndex; CK_ATTRIBUTE setTemplate; SECStatus rv; CK_MECHANISM_INFO mechanism_info; CK_OBJECT_CLASS keyClass; SECItem *cka_id; PRBool haslock = PR_FALSE; PRBool pubIsToken = PR_FALSE; PORT_Assert(slot != NULL); if (slot == NULL) { PORT_SetError( SEC_ERROR_NO_MODULE); return NULL; } /* if our slot really doesn't do this mechanism, Generate the key * in our internal token and write it out */ if (!PK11_DoesMechanism(slot,type)) { PK11SlotInfo *int_slot = PK11_GetInternalSlot(); /* don't loop forever looking for a slot */
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?