diff options
author | Ingela Anderton Andin <ingela@erlang.org> | 2010-09-09 17:07:22 +0200 |
---|---|---|
committer | Ingela Anderton Andin <ingela@erlang.org> | 2010-09-10 12:16:34 +0200 |
commit | 6cced538abd4f8053c009b163efa8c6d568b9580 (patch) | |
tree | 20bd2188463ef85a9af163355f4da6bdaccd0e7a /lib/public_key | |
parent | fb29cd6c08a77778fdf7258f5682108e46fe26af (diff) | |
download | otp-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.hrl | 6 | ||||
-rw-r--r-- | lib/public_key/src/pubkey_cert.erl | 91 | ||||
-rw-r--r-- | lib/public_key/src/public_key.erl | 5 | ||||
-rw-r--r-- | lib/public_key/test/public_key_SUITE.erl | 8 |
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, _} = |