summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/catlfish.erl20
-rw-r--r--src/x509.erl50
2 files changed, 21 insertions, 49 deletions
diff --git a/src/catlfish.erl b/src/catlfish.erl
index 3b81baa..50811a1 100644
--- a/src/catlfish.erl
+++ b/src/catlfish.erl
@@ -91,24 +91,12 @@ serialise_signature_type(certificate_timestamp) ->
<<0:8>>;
serialise_signature_type(tree_hash) ->
<<1:8>>.
-%% deserialise_signature_type(<<0:8>>) ->
-%% certificate_timestamp;
-%% deserialise_signature_type(<<1:8>>) ->
-%% tree_hash.
-
-%% build_mtl(Timestamp, LeafCert) ->
-%% TSE = #timestamped_entry{timestamp = Timestamp,
-%% entry_type = x509_entry,
-%% signed_entry = LeafCert},
-%% MTL = #mtl{leaf_version = v1,
-%% leaf_type = timestamped_entry,
-%% entry = TSE},
-%% serialise(MTL).
calc_sct(TimestampedEntry) ->
- plop:serialise(plop:spt(list_to_binary([<<?PROTOCOL_VERSION:8>>,
- serialise_signature_type(certificate_timestamp),
- serialise(TimestampedEntry)]))).
+ plop:serialise(
+ plop:spt(list_to_binary([<<?PROTOCOL_VERSION:8>>,
+ serialise_signature_type(certificate_timestamp),
+ serialise(TimestampedEntry)]))).
get_sct(Hash, TimestampedEntry) ->
case application:get_env(catlfish, sctcache_root_path) of
diff --git a/src/x509.erl b/src/x509.erl
index 43b90b3..e8c4f2b 100644
--- a/src/x509.erl
+++ b/src/x509.erl
@@ -14,6 +14,9 @@
encoding_invalid}.
-define(MAX_CHAIN_LENGTH, 10).
+-define(LEAF_POISON_OID, {1,3,6,1,4,1,11129,2,4,3}).
+-define(LEAF_POISON_VAL, [5,0]).
+-define(CA_POISON_OID, {1,3,6,1,4,1,11129,2,4,4}).
-spec normalise_chain([binary()], [binary()]) -> {ok, [binary()]} |
{error, reason()}.
@@ -41,9 +44,7 @@ read_pemfiles_from_dir(Dir) ->
[];
{ok, Filenames} ->
Files = lists:filter(
- fun(F) ->
- string:equal(".pem", filename:extension(F))
- end,
+ fun(F) -> string:equal(".pem", filename:extension(F)) end,
Filenames),
ders_from_pemfiles(Dir, Files)
end.
@@ -61,6 +62,8 @@ detox(LeafDer, ChainDer) ->
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%% Private functions.
+-spec normalise_chain([binary()], [binary()], integer()) ->
+ {false, reason()} | {true, list()}.
%% @doc Verify that the leaf cert or precert has a valid chain back to
%% an acceptable root cert. The order of certificates in the second
%% argument is: leaf cert in head, chain in tail. Order of first
@@ -71,8 +74,6 @@ detox(LeafDer, ChainDer) ->
%% amongst the acceptable root certs. Otherwise it contains exactly
%% one element, a CA cert from the acceptable root certs signing the
%% root of the chain.
--spec normalise_chain([binary()], [binary()], integer()) ->
- {false, reason()} | {true, list()}.
normalise_chain(_, _, MaxChainLength) when MaxChainLength =< 0 ->
%% Chain too long.
{false, chain_too_long};
@@ -98,11 +99,11 @@ normalise_chain(AcceptableRootCerts, [BottomCert|Rest], MaxChainLength) ->
false -> {false, signature_mismatch}
end.
+-spec signer(binary(), [binary()]) -> notfound | binary().
%% @doc Return first cert in list signing Cert, or notfound. NOTE:
%% This is potentially expensive. It'd be more efficient to search for
%% Cert.issuer in a list of Issuer.subject's. If so, maybe make the
%% matching somewhat fuzzy unless that too is expensive.
--spec signer(binary(), [binary()]) -> notfound | binary().
signer(_Cert, []) ->
notfound;
signer(Cert, [H|T]) ->
@@ -132,7 +133,6 @@ extract_verify_data(Cert, DerCert) ->
{_, Sig} = Cert#'Certificate'.signature,
SigAlgRecord = Cert#'Certificate'.signatureAlgorithm,
SigAlg = SigAlgRecord#'AlgorithmIdentifier'.algorithm,
- lager:debug("SigAlg: ~p", [SigAlg]),
try
{DigestType, _} = public_key:pkix_sign_types(SigAlg),
{ok, {PlainText, DigestType, Sig}}
@@ -160,10 +160,6 @@ verify_sig2(IssuerSPKI, {DigestOrPlainText, DigestType, Signature}) ->
algorithm = #'AlgorithmIdentifier'{algorithm = Alg, parameters = Params},
subjectPublicKey = {0, Key0}} = IssuerSPKI,
KeyType = pubkey_cert_records:supportedPublicKeyAlgorithms(Alg),
- lager:debug("Alg: ~p", [Alg]),
- lager:debug("Params: ~p", [Params]),
- lager:debug("KeyType: ~p", [KeyType]),
- lager:debug("Key0: ~p", [Key0]),
IssuerKey =
case KeyType of
'RSAPublicKey' ->
@@ -176,12 +172,6 @@ verify_sig2(IssuerSPKI, {DigestOrPlainText, DigestType, Signature}) ->
lager:error("NIY: Issuer key type ~p", [KeyType]),
false
end,
-
- lager:debug("DigestOrPlainText: ~p", [DigestOrPlainText]),
- lager:debug("DigestType: ~p", [DigestType]),
- lager:debug("Signature: ~p", [Signature]),
- lager:debug("IssuerKey: ~p", [IssuerKey]),
-
%% Verify the signature.
public_key:verify(DigestOrPlainText, DigestType, Signature, IssuerKey).
@@ -208,23 +198,23 @@ parsable_cert_p(Der) ->
end.
%% Precerts according to RFC6962.
-
+%%
%% Submitted precerts have a special critical poison extension -- OID
%% 1.3.6.1.4.1.11129.2.4.3, whose extnValue OCTET STRING contains
%% ASN.1 NULL data (0x05 0x00).
-
+%%
%% They are signed with either the CA cert that will sign the final
%% cert or a Precertificate Signing Certificate directly signed by the
%% CA cert that will sign the final cert. A Precertificate Signing
%% Certificate has CA:true and Extended Key Usage: Certificate
%% Transparency, OID 1.3.6.1.4.1.11129.2.4.4.
-
+%%
%% PreCert in SignedCertificateTimestamp does _not_ contain the poison
%% extension, nor does it have an issuer which is a Precertificate
%% Signing Certificate. This means that we have to 1) remove the
%% poison extension and 2) potentially change issuer and Authority Key
%% Identifier. See RFC6962 Section 3.2.
-
+%%
%% Changes in draft-ietf-trans-rfc6962-bis-??: TODO.
-spec detox_precert(binary(), binary(), binary()) -> {binary(), binary()}.
@@ -282,17 +272,15 @@ set_issuer_and_authkeyid(TBSCert,
lager:debug("swapping auth key id to ~p",
[ParentAuthKeyExt]),
ParentAuthKeyExt;
- Orig ->
- Orig
+ _ -> E
end
end,
TBSCert#'TBSCertificate'.extensions),
+ lager:debug("setting issuer and auth key id", []),
TBSCert#'TBSCertificate'{issuer = ParentIssuer,
extensions = NewExtensions}
end.
--define(CA_POISON_OID, {1,3,6,1,4,1,11129,2,4,4}).
-
-spec is_precert_signer(#'Certificate'{}) -> boolean().
is_precert_signer(#'Certificate'{tbsCertificate = TBSCert}) ->
Extensions = pubkey_cert:extensions_list(TBSCert#'TBSCertificate'.extensions),
@@ -323,14 +311,10 @@ is_ca(#'TBSCertificate'{extensions = Extensions}) ->
-spec remove_poison_ext(#'Certificate'{}) -> #'TBSCertificate'{}.
remove_poison_ext(#'Certificate'{tbsCertificate = TBSCert}) ->
- Extensions = pubkey_cert:extensions_list(TBSCert#'TBSCertificate'.extensions),
- SanitisedExtensions =
- filter(fun(E) -> not poisoned_leaf_p(E) end, Extensions),
- NewTBSCert = TBSCert#'TBSCertificate'{extensions = SanitisedExtensions},
- NewTBSCert.
-
--define(LEAF_POISON_OID, {1,3,6,1,4,1,11129,2,4,3}).
--define(LEAF_POISON_VAL, [5,0]).
+ Extensions =
+ filter(fun(E) -> not poisoned_leaf_p(E) end,
+ pubkey_cert:extensions_list(TBSCert#'TBSCertificate'.extensions)),
+ TBSCert#'TBSCertificate'{extensions = Extensions}.
poisoned_leaf_p(#'Extension'{extnID = ?LEAF_POISON_OID,
critical = true,