diff options
-rw-r--r-- | Makefile | 5 | ||||
-rw-r--r-- | src/catlfish.erl | 19 | ||||
-rw-r--r-- | src/v1.erl | 18 | ||||
-rw-r--r-- | src/x509.erl | 6 |
4 files changed, 28 insertions, 20 deletions
@@ -131,6 +131,11 @@ tests-createcert: ) cp $(INSTDIR)/tests/httpsca/httpscert-1.pem $(INSTDIR)/tests/httpscert/ +dialyze: build + dialyzer ebin + +tags: + etags src/*.[he]rl # Unit testing. check: all diff --git a/src/catlfish.erl b/src/catlfish.erl index 4410203..d1f4425 100644 --- a/src/catlfish.erl +++ b/src/catlfish.erl @@ -10,7 +10,7 @@ -define(PROTOCOL_VERSION, 0). -%%-type signature_type() :: certificate_timestamp | tree_hash | test. % uint8 +-type signature_type() :: certificate_timestamp | tree_hash | test. % uint8 -type entry_type() :: x509_entry | precert_entry | test. % uint16 -type leaf_type() :: timestamped_entry | test. % uint8 -type leaf_version() :: v1 | v2. % uint8 @@ -88,11 +88,9 @@ deserialise_entry_type(<<0:16>>) -> deserialise_entry_type(<<1:16>>) -> precert_entry. --spec serialise_signature_type(certificate_timestamp|tree_hash) -> binary(). +-spec serialise_signature_type(signature_type()) -> binary(). serialise_signature_type(certificate_timestamp) -> - <<0:8>>; -serialise_signature_type(tree_hash) -> - <<1:8>>. + <<0:8>>. calc_sct(TimestampedEntry) -> plop:serialise( @@ -115,9 +113,10 @@ get_sct(Hash, TimestampedEntry) -> calc_sct(TimestampedEntry) end. --spec add_chain(binary(), [binary()], normal|precert) -> nonempty_string(). +-spec add_chain(binary(), [binary()], normal|precert) -> {[{_,_},...]}. add_chain(LeafCert, CertChain, Type) -> - EntryHash = crypto:hash(sha256, [LeafCert | CertChain]), + CombinedChain = [LeafCert | CertChain], + EntryHash = crypto:hash(sha256, CombinedChain), EntryType = case Type of normal -> x509_entry; precert -> precert_entry @@ -134,7 +133,7 @@ add_chain(LeafCert, CertChain, Type) -> ExtraData = case Type of normal -> CertChain; - precert -> [LeafCert | CertChain] + precert -> CombinedChain end, LogEntry = list_to_binary( @@ -219,11 +218,11 @@ deserialise_signed_precert_entry(Data) -> tbs_certificate = TBSCertificate}, RestData2}. --spec entries(non_neg_integer(), non_neg_integer()) -> list(). +-spec entries(non_neg_integer(), non_neg_integer()) -> {[{entries, list()},...]}. entries(Start, End) -> {[{entries, x_entries(plop:get(Start, End))}]}. --spec entry_and_proof(non_neg_integer(), non_neg_integer()) -> list(). +-spec entry_and_proof(non_neg_integer(), non_neg_integer()) -> {[{_,_},...]}. entry_and_proof(Index, TreeSize) -> case plop:inclusion_and_entry(Index, TreeSize) of {ok, Entry, Path} -> @@ -126,11 +126,8 @@ add_chain(Input, Type) -> case (catch mochijson2:decode(Input)) of {error, E} -> html("add-chain: bad input:", E); - {struct, [{<<"chain">>, ChainBase64}]} -> - case (catch [base64:decode(X) || X <- ChainBase64]) of - {'EXIT', _} -> - html("add-chain: invalid base64-encoded chain: ", - [ChainBase64]); + {struct, [{<<"chain">>, ChainB64List}]} -> + case decode_chain(ChainB64List) of [LeafCert | CertChain] -> case x509:normalise_chain(catlfish:known_roots(), [LeafCert|CertChain]) of @@ -143,8 +140,15 @@ add_chain(Input, Type) -> [x509:cert_string(LeafCert), Reason]), html("add-chain: invalid chain", Reason) end; - Invalid -> - html("add-chain: chain is not a list: ", [Invalid]) + {invalid, ErrText} -> + html(io:format("add-chain: ~p", [ErrText]), [ChainB64List]) end; _ -> html("add-chain: missing input: chain", Input) end. + +-spec decode_chain(string()) -> {invalid, string()} | [binary()]. +decode_chain(B64List) -> + case (catch [base64:decode(X) || X <- B64List]) of + {'EXIT', _} -> {invalid, "invalid base64-encoded chain"}; + L -> L + end. diff --git a/src/x509.erl b/src/x509.erl index 87d9c0c..7bbfb8e 100644 --- a/src/x509.erl +++ b/src/x509.erl @@ -56,7 +56,7 @@ self_signed(L) -> lists:filter(fun(Cert) -> signed_by_p(Cert, Cert) end, L). -spec detox(binary(), [binary()]) -> {binary(), binary()}. -%% @doc Return the detoxed cet in LeafDer and the issuer leaf hash. +%% @doc Return a detoxed LeafDer and its issuer. detox(LeafDer, ChainDer) -> detox_precert(LeafDer, nth(1, ChainDer), nth(2, ChainDer)). @@ -64,7 +64,7 @@ detox(LeafDer, ChainDer) -> %% Private functions. -spec normalise_chain([binary()], [binary()], integer()) -> - {false, reason()} | {true, list()}. + {false, reason()} | {true, [binary()]}. %% @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 @@ -312,7 +312,7 @@ is_precert_signer(#'Certificate'{tbsCertificate = TBSCert}) -> _ -> false end. --spec is_ca(#'TBSCertificate'{}) -> binary(). +-spec is_ca(#'TBSCertificate'{}) -> boolean(). is_ca(#'TBSCertificate'{extensions = Extensions}) -> case pubkey_cert:select_extension(?'id-ce-basicConstraints', Extensions) of #'Extension'{critical = true, extnValue = Val} -> |