[Freeipa-devel] LDAP schema for DNSSEC keys

Petr Spacek pspacek at redhat.com
Fri Jun 20 18:04:04 UTC 2014


On 12.6.2014 16:23, Petr Spacek wrote:
> On 30.4.2014 18:19, Petr Spacek wrote:
>> following text summarizes schema & DIT layout for DNSSEC key storage in LDAP.
>
> I have added object classes and default values for attributes I consider
> important. This is final proposal for implementation. Please review it ASAP.
>
>> This is subset of full PKCS#11 schema [0]. It stores bare keys with few
>> metadata attributes when necessary.
>>
>> The intention is to make transition to full PKCS#11-in-LDAP schema [0] as easy
>> as possible. This transition should happen in next minor version of FreeIPA.
>>
>> In theory, the transition should be just adding few object classes to existing
>> objects and populating few new metadata attributes. Related object classes are
>> marked below with "(in long-term)".
>>
>> Please comment on it soon. We want to implement it ASAP :-)
>>
>>
>> DNSSEC key
>> ==========
>> - Asymmetric
>> - Private key is stored in LDAP as encrypted PKCS#8 blob
>> - Public key is published in LDAP
>> - Encrypted with symmetric "DNSSEC master key" (see below)
>> - Private key - represented as LDAP object with object classes:
>> ipaEPrivateKey  [1] # encrypted data
>> ipaWrappedKey   [2] # pointer to master key, outside scope of pure PKCS#11
>> ipk11PrivateKey [3] (in long-term) # PKCS#11 metadata
>> - Public key - represented as LDAP object with object classes:
>> ipaPublicKey    [1] # public key data
>> ipk11PublicKey  [3] (in long-term) # PKCS#11 metadata
>>
>>
>> Master key
>> ==========
>> - Symmetric
>> - Stored in LDAP as encrypted blob
>> - Encrypted with asymmetric "replica key" (see below)
>> - 1 replica = 1 blob, n replicas = n blobs encrypted with different keys
>> - A replica uses it's own key for master key en/decryption
>> - Represented as LDAP object with object classes:
>> ipaESecretKey  [1]
>> ipk11SecretKey [3] (in long-term)
>>
>> Replica key
>> ===========
>> - Asymmetric
>> - Private key is stored on replica's disk only
>> - Public key for all replicas is stored in LDAP
>> - Represented as LDAP object with object classes:
>> ipaPublicKey   [1]
>> ipk11PublicKey [3] (in long-term)
>>
>>
>> DIT layout
>> ==========
>>   DNSSEC key material
>>   -------------------
>>   - Container: cn=keys, cn=sec, cn=dns, dc=example
>>   - Private and public keys are stored as separate objects to accommodate all
>> PKCS#11 metadata.
>>   - We need to decide about object naming:
>>    - One obvious option for RDN is to use uniqueID but I don't like it. It is
>> hard to read for humans.
>>    - Other option is to use uniqueID+PKCS#11 label or other attributes to make
>> it more readable. Can we use multi-valued RDN? If not, why? What are technical
>> reasons behind it?
>>
>> It is question if we like:
>>   nsUniqID = 0b0b7e53-957d11e3-a51dc0e5-9a05ecda
>>   nsUniqID = 8ae4190d-957a11e3-a51dc0e5-9a05ecda
>> more than:
>>   ipk11Label=meaningful_label+ipk11Private=TRUE
>>   ipk11Label=meaningful_label+ipk11Private=FALSE
>
> dn: ipk11Label=zone1_keyid123_public, cn=keys, cn=sec, cn=dns, dc=example
> objectClass: ipk11Object
> objectClass: ipk11PublicKey
> objectClass: ipaPublicKeyObject
> ipk11UniqueId: <UUID>
> ipk11Label: zone1_keyid123_public
> ipk11Wrap: FALSE
> ipk11Verify: TRUE
> ipaPublicKey: <public key>
>
> dn: ipk11Label=zone1_keyid123_private, cn=keys, cn=sec, cn=dns, dc=example
> objectClass: ipk11Object
> objectClass: ipk11PrivateKey
> objectClass: ipaPrivateKeyObject
> objectClass: ipaWrappedKey
> ipaWrappingKey:ipk11Label=dnssec_m1,cn=master,cn=keys,cn=sec,cn=dns,dc=example
> ipk11Sign: TRUE
> ipk11Decrypt: FALSE
> ipk11Unwrap: FALSE
> ipaPrivateKey: <blob encrypted with DNSSEC master key>
>
>
>>   DNSSEC key metadata
>>   -------------------
>>   - Container (per-zone): cn=keys, idnsname=example.net, cn=dns
>>   - Key metadata can be linked to key material via DN or ipk11Id.
>>   - This allows key sharing between zones.
>> (DNSSEC-metadata will be specified later. That is not important for key
>> storage.)
> This will be sorted out in separate thread.
>
>>
>>   Replica public keys
>>   -------------------
>>   - Container: cn=DNS,cn=<replica FQDN>,cn=masters,cn=ipa,cn=etc,dc=example
>>    - or it's child object like cn=wrappingKey
>
> - Please note that private part of this key is stored on disk.
>
> dn: ipk11Label=wrapkey_replica1,cn=DNS,cn=<replica
> FQDN>,cn=masters,cn=ipa,cn=etc,dc=example
> objectClass: ipk11Object
> objectClass: ipk11PublicKey
> objectClass: ipaPublicKeyObject
> ipk11UniqueId: <UUID>
> ipk11Label: wrapkey_replica1
> ipk11Wrap: TRUE
> ipk11Encrypt: FALSE
> ipk11Verify: FALSE
> ipaPublicKey: <public key>
>
>>   Master keys
>>   -----------
>>   - Container: cn=master, cn=keys, cn=sec, cn=dns, dc=example
>>   - Single key = single object.
>>   - We can use ipk11Label or ipk11Id for naming:
>>   ipk11Label=dnssecMaster1, ipk11Label=dnssecMaster2, etc.
>
> dn: ipk11Label=dnssec_m1, cn=master, cn=keys, cn=sec, cn=dns, dc=example
> objectClass: ipk11Object
> objectClass: ipk11SecretKey
> objectClass: ipaWrappedKey
> objectClass: ipaSecretKeyObject
> ipk11UniqueId: <UUID>
> ipk11Label: dnssec_m1
> ipk11Wrap: TRUE
> ipk11UnWrap: TRUE
> ipk11Encrypt: FALSE
> ipk11Decrypt: FALSE
> ipk11Sign: FALSE
> ipk11Verify: FALSE
> ipaWrappingAlgo: <algorithm used for key wrapping>
> ipaSecretKeyWrappedData: <encrypted blob for replica-1>
> ipaSecretKeyWrappedData: <encrypted blob for replica-2>
> ipaWrappingKey: <DN of replica-1 public key>
> ipaWrappingKey: <DN of replica-2 public key>

Today it turned out that storing private and public keys in separate LDAP 
objects is probably not necessary and makes things harder to manage. (Risk of 
dangling objects, you have to do LDAP searches all the time, keep PKCS#11 
metadata in sync between objects etc.)

In fact, IPA clients should never see none of those key objects. Clients  will 
work only with DNSKEY records in DNS tree but never with raw keys. Raw keys 
are useless to clients anyway because raw keys do not contain necessary DNSSEC 
metadata (as one key can be, in theory, shared among multiple DNS zones etc).


Honza proposed to combine ipk11PublicKey and ipk11PrivateKey objects under 
single object which makes perfect sense because almost all PKCS#11 data can be 
shared (label, ID, PKCS#11 timestamps etc.).

If I'm not wrong, the only problem is that two of PKCS#11 attributes can have 
different value for public and private part of the key.

The complete list of "shared" attributes between the ipk11PublicKey and 
ipk11PrivateKey object classes contains 13 attributes. However, it doesn't 
make sense to store different values for most of them.

I looked into it a bit. It seems that following attributes are shared but they 
should always have the same value (i.e. they probably have to be copied from 
one object to the other if we decide to stay with separate objects):

ipk11AllowedMechanisms
ipk11Destroyable
ipk11KeyGenMechanism
ipk11KeyType
ipk11Label
ipk11Id
ipk11Local
ipk11Modifiable
ipk11StartDate
ipk11EndDate
ipk11Derive


Remaining two attributes are common for all PKCS#11 objects but it makes sense 
to have different values for private/public keys (or certificates):

ipk11Private
ipk11Copyable

Honza proposed to use LDAP subtypes for those "conflicting" attributes and 
store attribute values for private/public key/certificate in sub-types with 
names defined by object class (without ipk11 prefix).

Example:
Public key is represented as ipk11PublicKey object class, private key as 
ipk11PrivateKey. All-on-one-object can look like:

dn: ipk11Label=zone2-ksk,cn=keys,cn=sec,cn=dns,dc=ipa,dc=example
objectClass: ipaWrappedKey
objectClass: ipaPrivateKeyObject
objectClass: ipaPublicKeyObject
objectClass: ipk11Object
objectClass: ipk11PrivateKey
objectClass: top
objectClass: ipk11StorageObject
objectClass: ipk11Key
objectClass: ipk11PublicKey
ipaWrappingKey: ipk11Label=dnssec-master-2,cn=master,cn=keys,cn=sec,cn=dns,d
  c=ipa,dc=example
ipk11UniqueId: UUID4
ipaPrivateKey:: ZW5jcnlwdGVkIGJsb2I=
ipaPublicKey:: cHVibGljIGtleSBkYXRh
ipk11Decrypt: FALSE
ipk11Encrypt: FALSE
ipk11Label: zone2-allinone
ipk11Private;privatekey: TRUE
ipk11Private;publickey: FALSE
ipk11Sign: TRUE
ipk11Unwrap: FALSE
ipk11Verify: TRUE
ipk11Wrap: FALSE


What do you think about it?

Given that there are only two really conflicting attributes, I think it is 
easier to deal with sub-types for these two and do not add complexity and 
overhead connected with managing multiple objects, pairing of them, error 
handling if write to one object succeeds but fails for the other etc.

If we later discover that this "object sharing" limits us we can migrate to 
fully separate objects. This part of the tree will be visible only to IPA 
servers so no client changes will be required.


I'm attaching LDIF with example how DIT for DNSSEC keys will look like. It 
contains one example with key pair split between two objects and one example 
with keypair stored in one object. In also contains DNSSEC metadata objects, 
master key and replica key.

Have a nice weekend!

Petr^2 Spacek

>> Work flows
>> ==========
>>   Read DNSSEC private key
>>   -----------------------
>>    1) read DNSSEC private key from LDAP
>>    2) ipaWrappedKey objectClass is present - key is encrypted
>>    3) read master key denoted by ipaWrappingKey attribute in DNSSEC key object
>>    4) use local replica key to decrypt master key
>>    5) use decrypted master key to decrypt DNSSEC private key
>>
>>   Add DNSSEC private key
>>   ----------------------
>>    1) use local replica key to decrypt master key
>>    2) encrypt DNSSEC private key with master key
>>    3) add ipaWrappingKey attribute pointing to master key
>>    4) store encrypted blob in a new LDAP object
>>
>>   Add a replica
>>   -------------
>>   ipa-replica-prepare:
>>    1) generate a new replica-key pair for the new replica
>>    2) store key pair to replica-file (don't scream yet :-)
>>    4) add public key for the new replica to LDAP
>>    3) fetch master key from LDAP
>>    4) encrypt master key with new replica public key
>>    5) store resulting master key blob to LDAP
>>   ipa-replica-install:
>>    6) generate a new replica-key pair (!)
>>    7) store new public key to LDAP
>>    8) remove old public key (from replica-file) from LDAP
>>    9) fetch master key
>>   10) decrypt master key using old private key (from replica-file)
>>   11) encrypt master key using new private key (generated locally)
>>   12) replace old master key blob in LDAP with new blob (from step 11)
>>
>>   Delete a replica
>>   ----------------
>> This is the tricky part. New master key has to be generated on some other
>> replica. What should we do if the ipa-replica-manage command was run on
>> deleted replica?
>>
>> I propose to split replica master key roll-over to two phases:
>>   Any machine in IPA domain (including to-be deleted replica):
>>    1) Delete public key associated with replica from LDAP
>>    2) Flip a bit in master key metadata and say "this key needs to be
>> re-generated"
>>       (Maybe we can disable ipk11Wrap boolean to indicate that this key should
>> not be used for key wrapping.)
>>
>>   Remaining replicas:
>>    3) Periodically check that master key is obsolete
>>    4) Wait for (random period of time) to limit probability of collision
>>    5) Check that master key is really obsolete and new one is not present
>>    6) Generate a new master key
>>    7) Encrypt new master key with all replica-public-keys stored in LDAP
>>    8) Store new master key blobs to a new LDAP object
>>       (Conflicts are not a problem up to now because we are not deleting old
>> key. In worst case, we will have multiple new master keys.)
>> *What should we do now?*
>>    9) ??? Re-encrypt all DNSSEC keys with a new master key? (What if we have
>> write conflict now?)
>>       ??? Let old keys there and wait until key rotation mechanism replaces
>> all old DNSSEC keys with new DNSSEC keys encrypted with a new master key (~
>> one year)?
>>   10) Old master key can be deleted when no other object is referencing to it.
>>
>>
>> Congratulations to people who reached this line and didn't skip anything :-)
>>
>> [0] http://www.freeipa.org/page/V4/PKCS11_in_LDAP/Schema
>> [1] http://www.freeipa.org/page/V4/PKCS11_in_LDAP/Schema#Encoded_key_data_2
>> [2]
>> http://www.freeipa.org/page/V4/PKCS11_in_LDAP/Schema#FreeIPA_specifics_-_key_wrapping
>>
>>
>> [3] http://www.freeipa.org/page/V4/PKCS11_in_LDAP/Schema#Storage_objects
-------------- next part --------------
A non-text attachment was scrubbed...
Name: dnssec.ldif
Type: text/x-ldif
Size: 4543 bytes
Desc: not available
URL: <http://listman.redhat.com/archives/freeipa-devel/attachments/20140620/10a20c43/attachment.bin>


More information about the Freeipa-devel mailing list