@@ -69,14 +69,6 @@ internal sealed class CertificateAuthority : IDisposable
6969 } ,
7070 critical : false ) ;
7171
72- private static readonly X509EnhancedKeyUsageExtension s_tlsServerEku =
73- new X509EnhancedKeyUsageExtension (
74- new OidCollection
75- {
76- new Oid ( "1.3.6.1.5.5.7.3.1" , null )
77- } ,
78- false ) ;
79-
8072 private static readonly X509EnhancedKeyUsageExtension s_tlsClientEku =
8173 new X509EnhancedKeyUsageExtension (
8274 new OidCollection
@@ -106,6 +98,11 @@ internal sealed class CertificateAuthority : IDisposable
10698 internal DateTimeOffset ? RevocationExpiration { get ; set ; }
10799 internal bool CorruptRevocationIssuerName { get ; set ; }
108100
101+ // All keys created in this method are smaller than recommended,
102+ // but they only live for a few seconds (at most),
103+ // and never communicate out of process.
104+ const int DefaultKeySize = 1024 ;
105+
109106 internal CertificateAuthority (
110107 X509Certificate2 cert ,
111108 string aiaHttpUrl ,
@@ -159,25 +156,22 @@ internal X509Certificate2 CreateSubordinateCA(
159156 subject ,
160157 publicKey ,
161158 TimeSpan . FromMinutes ( 1 ) ,
162- new X509BasicConstraintsExtension (
163- certificateAuthority : true ,
164- depthLimit . HasValue ,
165- depthLimit . GetValueOrDefault ( ) ,
166- critical : true ) ,
167- s_caKeyUsage ,
168- ekuExtension : null ) ;
159+ new X509ExtensionCollection ( ) {
160+ new X509BasicConstraintsExtension (
161+ certificateAuthority : true ,
162+ depthLimit . HasValue ,
163+ depthLimit . GetValueOrDefault ( ) ,
164+ critical : true ) ,
165+ s_caKeyUsage } ) ;
169166 }
170167
171- internal X509Certificate2 CreateEndEntity ( string subject , RSA publicKey , X509Extension altName )
168+ internal X509Certificate2 CreateEndEntity ( string subject , RSA publicKey , X509ExtensionCollection extensions )
172169 {
173170 return CreateCertificate (
174171 subject ,
175172 publicKey ,
176173 TimeSpan . FromSeconds ( 2 ) ,
177- s_eeConstraints ,
178- s_eeKeyUsage ,
179- s_tlsServerEku ,
180- altName : altName ) ;
174+ extensions ) ;
181175 }
182176
183177 internal X509Certificate2 CreateOcspSigner ( string subject , RSA publicKey )
@@ -186,9 +180,7 @@ internal X509Certificate2 CreateOcspSigner(string subject, RSA publicKey)
186180 subject ,
187181 publicKey ,
188182 TimeSpan . FromSeconds ( 1 ) ,
189- s_eeConstraints ,
190- s_eeKeyUsage ,
191- s_ocspResponderEku ,
183+ new X509ExtensionCollection ( ) { s_eeConstraints , s_eeKeyUsage , s_ocspResponderEku } ,
192184 ocspResponder : true ) ;
193185 }
194186
@@ -248,11 +240,8 @@ private X509Certificate2 CreateCertificate(
248240 string subject ,
249241 RSA publicKey ,
250242 TimeSpan nestingBuffer ,
251- X509BasicConstraintsExtension basicConstraints ,
252- X509KeyUsageExtension keyUsage ,
253- X509EnhancedKeyUsageExtension ekuExtension ,
254- bool ocspResponder = false ,
255- X509Extension altName = null )
243+ X509ExtensionCollection extensions ,
244+ bool ocspResponder = false )
256245 {
257246 if ( _cdpExtension == null && CdpUri != null )
258247 {
@@ -275,8 +264,10 @@ private X509Certificate2 CreateCertificate(
275264 HashAlgorithmName . SHA256 ,
276265 RSASignaturePadding . Pkcs1 ) ;
277266
278- request . CertificateExtensions . Add ( basicConstraints ) ;
279- request . CertificateExtensions . Add ( keyUsage ) ;
267+ foreach ( X509Extension extension in extensions )
268+ {
269+ request . CertificateExtensions . Add ( extension ) ;
270+ }
280271
281272 // Windows does not accept OCSP Responder certificates which have
282273 // a CDP extension, or an AIA extension with an OCSP endpoint.
@@ -290,16 +281,6 @@ private X509Certificate2 CreateCertificate(
290281 request . CertificateExtensions . Add (
291282 new X509SubjectKeyIdentifierExtension ( request . PublicKey , false ) ) ;
292283
293- if ( ekuExtension != null )
294- {
295- request . CertificateExtensions . Add ( ekuExtension ) ;
296- }
297-
298- if ( altName != null )
299- {
300- request . CertificateExtensions . Add ( altName ) ;
301- }
302-
303284 byte [ ] serial = new byte [ sizeof ( long ) ] ;
304285 RandomNumberGenerator . Fill ( serial ) ;
305286
@@ -841,7 +822,9 @@ internal static void BuildPrivatePki(
841822 string testName = null ,
842823 bool registerAuthorities = true ,
843824 bool pkiOptionsInSubject = false ,
844- string subjectName = null )
825+ string subjectName = null ,
826+ int keySize = DefaultKeySize ,
827+ X509ExtensionCollection extensions = null )
845828 {
846829 bool rootDistributionViaHttp = ! pkiOptions . HasFlag ( PkiOptions . NoRootCertDistributionUri ) ;
847830 bool issuerRevocationViaCrl = pkiOptions . HasFlag ( PkiOptions . IssuerRevocationViaCrl ) ;
@@ -855,14 +838,15 @@ internal static void BuildPrivatePki(
855838 endEntityRevocationViaCrl || endEntityRevocationViaOcsp ,
856839 "At least one revocation mode is enabled" ) ;
857840
858- // All keys created in this method are smaller than recommended,
859- // but they only live for a few seconds (at most),
860- // and never communicate out of process.
861- const int KeySize = 1024 ;
841+ if ( extensions == null )
842+ {
843+ // default to client
844+ extensions = new X509ExtensionCollection ( ) { s_eeConstraints , s_eeKeyUsage , s_tlsClientEku } ;
845+ }
862846
863- using ( RSA rootKey = RSA . Create ( KeySize ) )
864- using ( RSA intermedKey = RSA . Create ( KeySize ) )
865- using ( RSA eeKey = RSA . Create ( KeySize ) )
847+ using ( RSA rootKey = RSA . Create ( keySize ) )
848+ using ( RSA intermedKey = RSA . Create ( keySize ) )
849+ using ( RSA eeKey = RSA . Create ( keySize ) )
866850 {
867851 var rootReq = new CertificateRequest (
868852 BuildSubject ( "A Revocation Test Root" , testName , pkiOptions , pkiOptionsInSubject ) ,
@@ -920,19 +904,11 @@ internal static void BuildPrivatePki(
920904 endEntityRevocationViaCrl ? cdpUrl : null ,
921905 endEntityRevocationViaOcsp ? ocspUrl : null ) ;
922906
923- X509Extension altName = null ;
924-
925- if ( ! String . IsNullOrEmpty ( subjectName ) )
926- {
927- SubjectAlternativeNameBuilder builder = new SubjectAlternativeNameBuilder ( ) ;
928- builder . AddDnsName ( subjectName ) ;
929- altName = builder . Build ( ) ;
930- }
931-
932907 endEntityCert = intermediateAuthority . CreateEndEntity (
933- BuildSubject ( subjectName ?? "A Revocation Test Cert" , testName , pkiOptions , pkiOptionsInSubject ) ,
934- eeKey ,
935- altName ) ;
908+ BuildSubject ( subjectName ?? "A Revocation Test Cert" , testName , pkiOptions , pkiOptionsInSubject ) ,
909+ eeKey ,
910+ extensions ) ;
911+
936912 endEntityCert = endEntityCert . CopyWithPrivateKey ( eeKey ) ;
937913 }
938914
0 commit comments