aboutsummaryrefslogtreecommitdiffstats
path: root/lib/public_key
diff options
context:
space:
mode:
authorIngela Anderton Andin <ingela@erlang.org>2010-09-09 17:07:22 +0200
committerIngela Anderton Andin <ingela@erlang.org>2010-09-10 12:16:34 +0200
commit6cced538abd4f8053c009b163efa8c6d568b9580 (patch)
tree20bd2188463ef85a9af163355f4da6bdaccd0e7a /lib/public_key
parentfb29cd6c08a77778fdf7258f5682108e46fe26af (diff)
downloadotp-6cced538abd4f8053c009b163efa8c6d568b9580.tar.gz
otp-6cced538abd4f8053c009b163efa8c6d568b9580.tar.bz2
otp-6cced538abd4f8053c009b163efa8c6d568b9580.zip
Improved certificate extension handling
Added the functionality so that the verification fun will be called when a certificate is considered valid by the path validation to allow access to eachs certificate in the path to the user application. Removed clause that only check that a extension is not critical, it does alter the verification rusult only withholds information from the application. Try to verify subject-AltName, if unable to verify it let application try.
Diffstat (limited to 'lib/public_key')
-rw-r--r--lib/public_key/include/public_key.hrl6
-rw-r--r--lib/public_key/src/pubkey_cert.erl91
-rw-r--r--lib/public_key/src/public_key.erl5
-rw-r--r--lib/public_key/test/public_key_SUITE.erl8
4 files changed, 51 insertions, 59 deletions
diff --git a/lib/public_key/include/public_key.hrl b/lib/public_key/include/public_key.hrl
index 82681502ab..a16eb10fe6 100644
--- a/lib/public_key/include/public_key.hrl
+++ b/lib/public_key/include/public_key.hrl
@@ -31,8 +31,10 @@
-define(DEFAULT_VERIFYFUN,
{fun(_,{bad_cert, _} = Reason, _) ->
{fail, Reason};
- (_,{extension, _}, UserState) ->
- {unknown, UserState}
+ (_,{extension, _}, UserState) ->
+ {unknown, UserState};
+ (_, valid, UserState) ->
+ {valid, UserState}
end, []}).
-record(path_validation_state, {
diff --git a/lib/public_key/src/pubkey_cert.erl b/lib/public_key/src/pubkey_cert.erl
index 7851981a30..e704c168f1 100644
--- a/lib/public_key/src/pubkey_cert.erl
+++ b/lib/public_key/src/pubkey_cert.erl
@@ -29,7 +29,7 @@
validate_revoked_status/3, validate_extensions/4,
normalize_general_name/1, digest_type/1, is_self_signed/1,
is_issuer/2, issuer_id/2, is_fixed_dh_cert/1,
- verify_data/1]).
+ verify_data/1, verify_fun/4]).
-define(NULL, 0).
@@ -288,6 +288,35 @@ is_fixed_dh_cert(#'OTPCertificate'{tbsCertificate =
Extensions}}) ->
is_fixed_dh_cert(SubjectPublicKeyInfo, extensions_list(Extensions)).
+
+%%--------------------------------------------------------------------
+-spec verify_fun(#'OTPTBSCertificate'{}, {bad_cert, atom()} | {extension, #'Extension'{}}|
+ valid, term(), fun()) -> term().
+%%
+%% Description: Gives the user application the opportunity handle path
+%% validation errors and unknown extensions and optional do other
+%% things with a validated certificate.
+%% --------------------------------------------------------------------
+verify_fun(Otpcert, Result, UserState0, VerifyFun) ->
+ case VerifyFun(Otpcert, Result, UserState0) of
+ {valid,UserState} ->
+ UserState;
+ {fail, Reason} ->
+ case Result of
+ {bad_cert, _} ->
+ throw(Result);
+ _ ->
+ throw({bad_cert, Reason})
+ end;
+ {unknown, UserState} ->
+ case Result of
+ {extension, #'Extension'{critical = true}} ->
+ throw({bad_cert, unknown_critical_extension});
+ _ ->
+ UserState
+ end
+ end.
+
%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
@@ -315,25 +344,6 @@ extensions_list(asn1_NOVALUE) ->
extensions_list(Extensions) ->
Extensions.
-verify_fun(Otpcert, Result, UserState0, VerifyFun) ->
- case VerifyFun(Otpcert, Result, UserState0) of
- {valid,UserState} ->
- UserState;
- {fail, Reason} ->
- case Result of
- {bad_cert, _} ->
- throw(Result);
- _ ->
- throw({bad_cert, Reason})
- end;
- {unknown, UserState} ->
- case Result of
- {extension, #'Extension'{critical = true}} ->
- throw({bad_cert, unknown_critical_extension});
- _ ->
- UserState
- end
- end.
extract_verify_data(OtpCert, DerCert) ->
{0, Signature} = OtpCert#'OTPCertificate'.signature,
@@ -538,47 +548,21 @@ validate_extensions(OtpCert, [#'Extension'{extnID = ?'id-ce-keyUsage',
end;
validate_extensions(OtpCert, [#'Extension'{extnID = ?'id-ce-subjectAltName',
- extnValue = Names} = Ext | Rest],
+ extnValue = Names,
+ critical = true} = Ext | Rest],
ValidationState, ExistBasicCon,
SelfSigned, UserState0, VerifyFun) ->
case validate_subject_alt_names(Names) of
- true when Names =/= [] ->
+ true ->
validate_extensions(OtpCert, Rest, ValidationState, ExistBasicCon,
SelfSigned, UserState0, VerifyFun);
false ->
- UserState = verify_fun(OtpCert, {bad_cert, invalid_subject_altname},
- UserState0, VerifyFun),
- validate_extensions(OtpCert, Rest, ValidationState, ExistBasicCon,
- SelfSigned, UserState, VerifyFun);
- other ->
UserState = verify_fun(OtpCert, {extension, Ext},
UserState0, VerifyFun),
validate_extensions(OtpCert, Rest, ValidationState, ExistBasicCon,
SelfSigned, UserState, VerifyFun)
end;
-%% This extension SHOULD NOT be marked critical. Its value
-%% does not have to be further validated at this point.
-validate_extensions(OtpCert, [#'Extension'{extnID = ?'id-ce-issuerAltName',
- extnValue = _} | Rest],
- ValidationState, ExistBasicCon,
- SelfSigned, UserState, VerifyFun) ->
- validate_extensions(OtpCert, Rest, ValidationState, ExistBasicCon,
- SelfSigned, UserState, VerifyFun);
-
-%% This extension MUST NOT be marked critical.Its value
-%% does not have to be further validated at this point.
-validate_extensions(OtpCert, [#'Extension'{extnID = Id,
- extnValue = _,
- critical = false} | Rest],
- ValidationState,
- ExistBasicCon, SelfSigned,
- UserState, VerifyFun)
- when Id == ?'id-ce-subjectKeyIdentifier';
- Id == ?'id-ce-authorityKeyIdentifier'->
- validate_extensions(OtpCert, Rest, ValidationState, ExistBasicCon,
- SelfSigned, UserState, VerifyFun);
-
validate_extensions(OtpCert, [#'Extension'{extnID = ?'id-ce-nameConstraints',
extnValue = NameConst} | Rest],
ValidationState,
@@ -592,7 +576,6 @@ validate_extensions(OtpCert, [#'Extension'{extnID = ?'id-ce-nameConstraints',
validate_extensions(OtpCert, Rest, NewValidationState, ExistBasicCon,
SelfSigned, UserState, VerifyFun);
-
validate_extensions(OtpCert, [#'Extension'{extnID = ?'id-ce-certificatePolicies',
critical = true} = Ext| Rest], ValidationState,
ExistBasicCon, SelfSigned, UserState0, VerifyFun) ->
@@ -653,13 +636,13 @@ is_valid_key_usage(KeyUse, Use) ->
lists:member(Use, KeyUse).
validate_subject_alt_names([]) ->
- true;
+ false;
validate_subject_alt_names([AltName | Rest]) ->
case is_valid_subject_alt_name(AltName) of
true ->
- validate_subject_alt_names(Rest);
+ true;
false ->
- false
+ validate_subject_alt_names(Rest)
end.
is_valid_subject_alt_name({Name, Value}) when Name == rfc822Name;
@@ -688,7 +671,7 @@ is_valid_subject_alt_name({directoryName, _}) ->
is_valid_subject_alt_name({_, [_|_]}) ->
true;
is_valid_subject_alt_name({otherName, #'AnotherName'{}}) ->
- other;
+ false;
is_valid_subject_alt_name({_, _}) ->
false.
diff --git a/lib/public_key/src/public_key.erl b/lib/public_key/src/public_key.erl
index 68bf04eeff..9c7817fa8e 100644
--- a/lib/public_key/src/public_key.erl
+++ b/lib/public_key/src/public_key.erl
@@ -539,6 +539,7 @@ validate(DerCert, #path_validation_state{working_issuer_name = Issuer,
user_state = UserState0,
verify_fun = VerifyFun} =
ValidationState0) ->
+
OtpCert = pkix_decode_cert(DerCert, otp),
UserState1 = pubkey_cert:validate_time(OtpCert, UserState0, VerifyFun),
@@ -556,10 +557,12 @@ validate(DerCert, #path_validation_state{working_issuer_name = Issuer,
%% We want the key_usage extension to be checked before we validate
%% the signature.
- UserState = pubkey_cert:validate_signature(OtpCert, DerCert,
+ UserState0 = pubkey_cert:validate_signature(OtpCert, DerCert,
Key, KeyParams, UserState5, VerifyFun),
+ UserState = pubkey_cert:verify_fun(OtpCert, valid, UserState0, VerifyFun),
ValidationState =
ValidationState1#path_validation_state{user_state = UserState},
+
pubkey_cert:prepare_for_next_cert(OtpCert, ValidationState).
sized_binary(Binary) when is_binary(Binary) ->
diff --git a/lib/public_key/test/public_key_SUITE.erl b/lib/public_key/test/public_key_SUITE.erl
index 46b8c3db8b..ea6a925139 100644
--- a/lib/public_key/test/public_key_SUITE.erl
+++ b/lib/public_key/test/public_key_SUITE.erl
@@ -377,7 +377,9 @@ pkix_path_validation(Config) when is_list(Config) ->
(_,{bad_cert, _} = Reason, _) ->
{fail, Reason};
(_,{extension, _}, UserState) ->
- {unknown, UserState}
+ {unknown, UserState};
+ (_, valid, UserState) ->
+ {valid, UserState}
end, []},
{ok, _} =
public_key:pkix_path_validation(Trusted, [Cert1, Cert3,Cert4],
@@ -392,7 +394,9 @@ pkix_path_validation(Config) when is_list(Config) ->
(_,{bad_cert, _} = Reason, _) ->
{fail, Reason};
(_,{extension, _}, UserState) ->
- {unknown, UserState}
+ {unknown, UserState};
+ (_, valid, UserState) ->
+ {valid, UserState}
end, []},
{ok, _} =