/* * copy a template of attributes from a source object to a target object. * if target object is not given, create it. */ static SECStatus pk11_copyAttributes(PLArenaPool *arena, PK11SlotInfo *targetSlot, CK_OBJECT_HANDLE targetID, PK11SlotInfo *sourceSlot, CK_OBJECT_HANDLE sourceID, CK_ATTRIBUTE *copyTemplate, CK_ULONG copyTemplateCount) { SECStatus rv; CK_ATTRIBUTE *newTemplate = NULL; CK_RV crv; crv = PK11_GetAttributes(arena, sourceSlot, sourceID, copyTemplate, copyTemplateCount); /* if we have missing attributes, just skip them and create the object */ if (crv == CKR_ATTRIBUTE_TYPE_INVALID) { CK_ULONG i, j; newTemplate = PORT_NewArray(CK_ATTRIBUTE, copyTemplateCount); if (!newTemplate) { return SECFailure; } /* remove the unknown attributes. If we don't have enough attributes * PK11_CreateNewObject() will fail */ for (i = 0, j = 0; i < copyTemplateCount; i++) { if (copyTemplate[i].ulValueLen != -1) { newTemplate[j] = copyTemplate[i]; j++; } } copyTemplate = newTemplate; copyTemplateCount = j; crv = PK11_GetAttributes(arena, sourceSlot, sourceID, copyTemplate, copyTemplateCount); } if (crv != CKR_OK) { PORT_SetError(PK11_MapError(crv)); return SECFailure; } if (targetID == CK_INVALID_HANDLE) { /* we need to create the object */ rv = PK11_CreateNewObject(targetSlot, CK_INVALID_SESSION, copyTemplate, copyTemplateCount, PR_TRUE, &targetID); } else { /* update the existing object with the new attributes */ rv = pk11_setAttributes(targetSlot, targetID, copyTemplate, copyTemplateCount); } if (newTemplate) { free(newTemplate); } return rv; }
/* * copy a template of attributes from a source object to a target object. * if target object is not given, create it. */ static SECStatus pk11_copyAttributes(PRArenaPool *arena, PK11SlotInfo *targetSlot, CK_OBJECT_HANDLE targetID, PK11SlotInfo *sourceSlot, CK_OBJECT_HANDLE sourceID, CK_ATTRIBUTE *copyTemplate, CK_ULONG copyTemplateCount) { SECStatus rv = PK11_GetAttributes(arena, sourceSlot, sourceID, copyTemplate, copyTemplateCount); if (rv != SECSuccess) { return rv; } if (targetID == CK_INVALID_HANDLE) { /* we need to create the object */ rv = PK11_CreateNewObject(targetSlot, CK_INVALID_SESSION, copyTemplate, copyTemplateCount, PR_TRUE, &targetID); } else { /* update the existing object with the new attributes */ rv = pk11_setAttributes(targetSlot, targetID, copyTemplate, copyTemplateCount); } return rv; }
SECStatus PK11_ImportAndReturnPrivateKey(PK11SlotInfo *slot, SECKEYRawPrivateKey *lpk, SECItem *nickname, SECItem *publicValue, PRBool isPerm, PRBool isPrivate, unsigned int keyUsage, SECKEYPrivateKey **privk, void *wincx) { CK_BBOOL cktrue = CK_TRUE; CK_BBOOL ckfalse = CK_FALSE; CK_OBJECT_CLASS keyClass = CKO_PRIVATE_KEY; CK_KEY_TYPE keyType = CKK_RSA; CK_OBJECT_HANDLE objectID; CK_ATTRIBUTE theTemplate[20]; int templateCount = 0; SECStatus rv = SECFailure; PRArenaPool *arena; CK_ATTRIBUTE *attrs; CK_ATTRIBUTE *signedattr = NULL; int signedcount = 0; CK_ATTRIBUTE *ap; SECItem *ck_id = NULL; arena = PORT_NewArena(2048); if(!arena) { return SECFailure; } attrs = theTemplate; PK11_SETATTRS(attrs, CKA_CLASS, &keyClass, sizeof(keyClass) ); attrs++; PK11_SETATTRS(attrs, CKA_KEY_TYPE, &keyType, sizeof(keyType) ); attrs++; PK11_SETATTRS(attrs, CKA_TOKEN, isPerm ? &cktrue : &ckfalse, sizeof(CK_BBOOL) ); attrs++; PK11_SETATTRS(attrs, CKA_SENSITIVE, isPrivate ? &cktrue : &ckfalse, sizeof(CK_BBOOL) ); attrs++; PK11_SETATTRS(attrs, CKA_PRIVATE, isPrivate ? &cktrue : &ckfalse, sizeof(CK_BBOOL) ); attrs++; switch (lpk->keyType) { case rsaKey: keyType = CKK_RSA; PK11_SETATTRS(attrs, CKA_UNWRAP, (keyUsage & KU_KEY_ENCIPHERMENT) ? &cktrue : &ckfalse, sizeof(CK_BBOOL) ); attrs++; PK11_SETATTRS(attrs, CKA_DECRYPT, (keyUsage & KU_DATA_ENCIPHERMENT) ? &cktrue : &ckfalse, sizeof(CK_BBOOL) ); attrs++; PK11_SETATTRS(attrs, CKA_SIGN, (keyUsage & KU_DIGITAL_SIGNATURE) ? &cktrue : &ckfalse, sizeof(CK_BBOOL) ); attrs++; PK11_SETATTRS(attrs, CKA_SIGN_RECOVER, (keyUsage & KU_DIGITAL_SIGNATURE) ? &cktrue : &ckfalse, sizeof(CK_BBOOL) ); attrs++; ck_id = PK11_MakeIDFromPubKey(&lpk->u.rsa.modulus); if (ck_id == NULL) { goto loser; } PK11_SETATTRS(attrs, CKA_ID, ck_id->data,ck_id->len); attrs++; if (nickname) { PK11_SETATTRS(attrs, CKA_LABEL, nickname->data, nickname->len); attrs++; } signedattr = attrs; PK11_SETATTRS(attrs, CKA_MODULUS, lpk->u.rsa.modulus.data, lpk->u.rsa.modulus.len); attrs++; PK11_SETATTRS(attrs, CKA_PUBLIC_EXPONENT, lpk->u.rsa.publicExponent.data, lpk->u.rsa.publicExponent.len); attrs++; PK11_SETATTRS(attrs, CKA_PRIVATE_EXPONENT, lpk->u.rsa.privateExponent.data, lpk->u.rsa.privateExponent.len); attrs++; PK11_SETATTRS(attrs, CKA_PRIME_1, lpk->u.rsa.prime1.data, lpk->u.rsa.prime1.len); attrs++; PK11_SETATTRS(attrs, CKA_PRIME_2, lpk->u.rsa.prime2.data, lpk->u.rsa.prime2.len); attrs++; PK11_SETATTRS(attrs, CKA_EXPONENT_1, lpk->u.rsa.exponent1.data, lpk->u.rsa.exponent1.len); attrs++; PK11_SETATTRS(attrs, CKA_EXPONENT_2, lpk->u.rsa.exponent2.data, lpk->u.rsa.exponent2.len); attrs++; PK11_SETATTRS(attrs, CKA_COEFFICIENT, lpk->u.rsa.coefficient.data, lpk->u.rsa.coefficient.len); attrs++; break; case dsaKey: keyType = CKK_DSA; /* To make our intenal PKCS #11 module work correctly with * our database, we need to pass in the public key value for * this dsa key. We have a netscape only CKA_ value to do this. * Only send it to internal slots */ if( publicValue == NULL ) { goto loser; } if (PK11_IsInternal(slot)) { PK11_SETATTRS(attrs, CKA_NETSCAPE_DB, publicValue->data, publicValue->len); attrs++; } PK11_SETATTRS(attrs, CKA_SIGN, &cktrue, sizeof(CK_BBOOL)); attrs++; PK11_SETATTRS(attrs, CKA_SIGN_RECOVER, &cktrue, sizeof(CK_BBOOL)); attrs++; if(nickname) { PK11_SETATTRS(attrs, CKA_LABEL, nickname->data, nickname->len); attrs++; } ck_id = PK11_MakeIDFromPubKey(publicValue); if (ck_id == NULL) { goto loser; } PK11_SETATTRS(attrs, CKA_ID, ck_id->data,ck_id->len); attrs++; signedattr = attrs; PK11_SETATTRS(attrs, CKA_PRIME, lpk->u.dsa.params.prime.data, lpk->u.dsa.params.prime.len); attrs++; PK11_SETATTRS(attrs,CKA_SUBPRIME,lpk->u.dsa.params.subPrime.data, lpk->u.dsa.params.subPrime.len); attrs++; PK11_SETATTRS(attrs, CKA_BASE, lpk->u.dsa.params.base.data, lpk->u.dsa.params.base.len); attrs++; PK11_SETATTRS(attrs, CKA_VALUE, lpk->u.dsa.privateValue.data, lpk->u.dsa.privateValue.len); attrs++; break; case dhKey: keyType = CKK_DH; /* To make our intenal PKCS #11 module work correctly with * our database, we need to pass in the public key value for * this dh key. We have a netscape only CKA_ value to do this. * Only send it to internal slots */ if (PK11_IsInternal(slot)) { PK11_SETATTRS(attrs, CKA_NETSCAPE_DB, publicValue->data, publicValue->len); attrs++; } PK11_SETATTRS(attrs, CKA_DERIVE, &cktrue, sizeof(CK_BBOOL)); attrs++; if(nickname) { PK11_SETATTRS(attrs, CKA_LABEL, nickname->data, nickname->len); attrs++; } ck_id = PK11_MakeIDFromPubKey(publicValue); if (ck_id == NULL) { goto loser; } PK11_SETATTRS(attrs, CKA_ID, ck_id->data,ck_id->len); attrs++; signedattr = attrs; PK11_SETATTRS(attrs, CKA_PRIME, lpk->u.dh.prime.data, lpk->u.dh.prime.len); attrs++; PK11_SETATTRS(attrs, CKA_BASE, lpk->u.dh.base.data, lpk->u.dh.base.len); attrs++; PK11_SETATTRS(attrs, CKA_VALUE, lpk->u.dh.privateValue.data, lpk->u.dh.privateValue.len); attrs++; break; /* what about fortezza??? */ default: PORT_SetError(SEC_ERROR_BAD_KEY); goto loser; } templateCount = attrs - theTemplate; PORT_Assert(templateCount <= sizeof(theTemplate)/sizeof(CK_ATTRIBUTE)); PORT_Assert(signedattr != NULL); signedcount = attrs - signedattr; for (ap=signedattr; signedcount; ap++, signedcount--) { pk11_SignedToUnsigned(ap); } rv = PK11_CreateNewObject(slot, CK_INVALID_SESSION, theTemplate, templateCount, isPerm, &objectID); /* create and return a SECKEYPrivateKey */ if( rv == SECSuccess && privk != NULL) { *privk = PK11_MakePrivKey(slot, lpk->keyType, !isPerm, objectID, wincx); if( *privk == NULL ) { rv = SECFailure; } } loser: if (ck_id) { SECITEM_ZfreeItem(ck_id, PR_TRUE); } return rv; }