[Freeipa-devel] DNSSEC support design considerations: key material handling

Simo Sorce simo at redhat.com
Mon Jul 15 19:07:26 UTC 2013


[..]
Removed first part that deals with old matters and keeping only the new
part. Comments inline as usual.

Simo.

On Mon, 2013-07-15 at 16:58 +0200, Petr Spacek wrote:
> The remaining part is mostly about key management.
> 
> Following text mentions 'DNSSEC keys' many times, so I tried to summarize how 
> keys are used in DNSSEC. Feel free to skip it.
> 
> == DNSSEC theory ==
> 
> Each zone has *at least* two key pairs. They are called Key Signing Key (KSK, 
> the first key pair) and Zone Signing Key (ZSK, the second key pair).
> 
> - *Parent* zone contains a copy of public part of the KSK.
> - Zone itself contains public part of ZSK (and KSK).
> - Client uses public part of KSK (obtained from secure parent zone) for ZSK 
> verification.
> - ZSK is used for signing of the real data in the zone (i.e. generating RRSIG 
> records) and verification on client side.
> 
> Each key and signature contains key-id, so one zone can be signed by multiple 
> KSKs and ZSKs at the same time. This solves the key roll over problem.
> 
> Each key contains this set of timestamps:
> Created, Revoke - self descriptive :-)
> Publish - public part of the key will be visible in zone after this time
> Active - new signatures with this key can be generated after this time
> Inactive - new signatures with this key cannot be generated after this time
> Delete - public part of the key will deleted from the zone after this time
> 
> NIST says [1] that KSK should be changed ~ each 1-3 years (it requires change 
> in parent zone) and ZSK should be changed ~ each 1-3 months.
> 
> The recommendation says [1] that zone should have two ZSKs: One Active (used 
> for signature generation) and second only Published (ready for roll over in 
> case of emergency/when the first key pair expires). This mitigates problems 
> with caches and stale key material during roll-over.
> 
> BIND 9 can do signature maintenance/ZSK key roll over automatically. It needs 
> only keys stored in files (with proper timestamps) and all signatures will be 
> generated & removed when the right time passes.

Is there any place I can read about the format and requirements of these
files ?

> KSK has to be rolled over manually because it requires changes in parent zone. 
> (It could be automated for sub-zones if their parent zone is also managed by 
> the same IPA server.)

Is there any provision for using DNSSEC with private DNS deployments ?
Or is this going to make sense only for IPA deployments that have valid
delegation from the public DNS system ?

Hmmm I guess that as long as the KSK in the 'parent' zone is imported
properly a private deployment of corp.myzone.com using the KSK of
myzone.com will work just fine even if corp.myzone.com is not actually
delegated but is a private DNS tree ?
Or is that incorrect ?

> == End of DNSSEC theory ==
> 
> 
> 
> 1) How will we handle generation of key pairs? How will externally generated 
> keys be imported?
> 
> Personally, I would start with 'classical' command line utilities like 
> dnssec-keygen etc. and extend 'ipa' tool to import generated keys. (Import = 
> read keys from text files and create appropriate attributes to LDAP.)

If you mean to do this as part of the ipa-dns-install script or
additional script (eg ipa-dnssec-enable) I am fine. I am not ok with
asking admins to manually run these commands.

> Initial key generation is closely related to the question how should we handle 
> (periodic) key regeneration? (e.g. "Generate new ZSK each month.")

We only really need to generate (or import) the KSK of the parent zone,
our code should be able to generate any other key, and sign it.

> Is it okay to use normal cron job to handle the key generation? I.e. to call 
> dnssec-keygen with proper parameters each month and store the result in LDAP?

No, the problem is that we need to define 'who' generates the keys.
Remember FreeIPA is a multimaster system, we cannot have potentially
conflicting cron jobs running on multiple servers.

> Or should we teach certmonger to take care of DNSSEC keys? Certmonger would 
> have to call dnssec-keygen and to do some IPA calls. (I assume that key 
> parsing and import will be handled by IPA framework.)

certmonger might have the same issue as a cronjob, how do we know
*which* one of 3 DNS server should run the updating job ?

Should we just leave it to chance and the first win ? What if 2 end up
trying to create new keys at exactly the same time ?

> We can postpone the key management for the first version and just provide 
> interface for key removal and import from file.

Well all this key management will be a FreeIPA issue, from the
bind-dyndb-ldap development pov we need to provide the mechanism and can
certainly defer the key management part, but we will not be able to
offer this feature until that is done.


> 2) Second question is how and where keys should be stored. AFAIK BIND 9 
> expects that keys will be stored in file system: One key pair as two files in 
> specified directory. We probably want to store keys in LDAP, as usual.
> 
> My proposal is to represent each key pair by object with new class 
> idnsDNSSECKey. This 'key pair object' will be stored inside zone container. E.g.
> DNS zone = idnsname=ipa.test,cn=dns,dc=ipa,dc=test
> Key pair = cn=005+01908,idnsname=ipa.test,cn=dns,dc=ipa,dc=test
> 
> Private key is represented by opaque blob (size ~ 1-2 kiB), so octetString 
> could be the right syntax:
> attributetypes: ( x.x.x.x.x NAME 'idnsSecPrivateKey' SYNTAX 
> 1.3.6.1.4.1.1466.115.121.1.40 SINGLE-VALUE )

Is this just a key ? Or does it contain further data ?

> Public key can be represented with normal DNSKEY record (size ~ 200-500 B), so 
> it would be possible to use normal DNSKEY attribute. I see two problems with 
> this approach:
> - DNSKEY record (= attribute) is multi-valued by definition, but only one 
> public key can be present in a key pair.
> - DNSKEY records will be managed automatically by BIND so we don't want to let 
> users to mess with them directly. DNSKEYRecord attribute is not defined at the 
> moment and I'm not willing to define it now.
> 
> For these reasons I think that we can define new public key attribute in the 
> same way as private key attribute:
> attributetypes: ( x.x.x.x.x NAME 'idnsSecPublicKey' SYNTAX 
> 1.3.6.1.4.1.1466.115.121.1.40 SINGLE-VALUE )
> 
> The resulting object class could be:
> objectClasses: ( x.x.x.x.x NAME 'idnsSecKeyPair' DESC 'DNSSEC key pair' SUP 
> top STRUCTURAL MUST ( cn $ idnsSecPrivateKey $ idnsSecPublicKey ) )

Will bind read these attributes ?
Or will we have to dump these values into files via bind-dyndb-ldap for
bind9 to read them back ?

> CN attribute is user readable key name. It could be anything. BIND's syntax 
> follows (text copied from dnssec-keyfromlabel):
> This is an identification string for the key files: String of the form 
> "Knnnn.+aaa+iiiii":
> - nnnn is the key name (zone name)
> - aaa is the numeric representation of the algorithm
> - iiiii is the key identifier (or footprint)
> 
> Naturally, we can omit leading "K" and zone name, because we know the name 
> from parent object in the LDAP/DIT. Also, it could be nice to indicate the 
> type of the key - KSK or ZSK.

ack, should we have an explicit attribute that tells us what type it
is ?

> Attribute idnsSecPrivateKey should be readable only by DNS admins (and DNS 
> servers :-). I'm not sure if we should make restrict read access even more. Is 
> there a valid reason for admin to read the blob? I don't know, but admin can 
> read the file on disk anyway ...

One weak reason to allow read by admins would be to allow them to
migrate away, but I do not like to put these keys completely unprotected
in LDAP. Given bind has a keytab I was thinking we may want to encrypt
these keys with the DNS long term key, however this complicates the code
slightly in 2 ways:
1. we can have multiple DNS Servers (ie multiple keys)
2. we need to allow for roll-over

To simplify the matter we would have to use a 'master key' that encrypts
all signing keys and is made available to DNS servers encrypted with
their keys.

Master key needs to allow for roll over in case it is compromised. But
we could deal with it by simply rolling also all DNS keys and encrypting
the new ones with the new key. After all if the key was compromised we
must assume all DNs signing keys may have been compromised so a full
roll-over is necessary. This simplifies the problem because it means we
will never need to store the same DNS signing key encrypted with
multiple 'master keys'.

A master key also allows for easy addition/removal of DNS servers as it
needs to be re-encrypted only once when a new DNS is added (or removed
and readded), and a server removal is just a delete operation.

>  From user interface point of view, key pairs are bit hard to deal with. 
> Private key format is algorithm-dependent, so the only universal way to get 
> standardized fields like valid-from/active-from/valid-to/revoked timestamps 
> etc. is to call parser from bind-libs.

Are these parsers available in public libs ?
Should we add these attributes explicitly in the 'idnsSecKeyPair'
objetclass instead and reconstruct the private key file from there ?
Or would that risk being incompatibile with a future new key type ?

If so should we really split key material in 2 attributes? Or should we
rather just load the full file content in a single attribute as an
opaque blob ?


> 3) How will the configuration be stored?
> Parameters are:
> - DNSSEC enabled/disabled for one zone or globally - proposal: add a new 
> boolean attribute idnsSecInlineSigning to zone and global config object

why not simply iDNSSECenabled: TRUE/FALSE ?

> - NSEC3 parameters - proposal: use standard NSEC3PARAM record in the zone

What are these ?

> The rest of the configuration options are related to the key management 
> problem. We need to know:
> - how many key pairs (e.g. 2 KSKs, 2 ZSKs)

Shouldn't we allow an arbitrary number ? Does bind have strict limits ?

> - when (e.g. generate new key pair 30 days before active key expires)

probably needs to be tunable. new attribute ?

> - of which key types (KSK or ZSK)
> - with which algorithms
> - with which key lengths
> should be generated. Note that we need to store configuration about X KSKs and 
> Y ZSKs.

seem all of these needs to be tunables and require their own
attributes ?

> Again, we can postpone the key management for the first version.

We can certainly postpone certain aspects of key management at least to
get development time down to a more quantifiable amount. But we'll not
be able to offer DNSSEC support in FreeIPA until there is management.

> 4) For future versions - do we plan to add support for PKCS#11 HSMs? BIND 9 
> can use OpenSSL for this stuff (somehow), but I didn't look into details.

I think this can be certainly postponed unless it may require changes in
the schema, in which case we may want to discuss if we need anything in
there so that the initial code can be future-proof.

> [1] http://csrc.nist.gov/publications/nistpubs/800-81r1/sp-800-81r1.pdf 
> section 9.3 Generation of Public Key-Private Key Pair (DNSSEC-OP1) page 9-5
> 
> 
> Congratulations, you reached end of the text :-)

Thanks, excellent write-up as always.

Simo.

-- 
Simo Sorce * Red Hat, Inc * New York




More information about the Freeipa-devel mailing list