33use crate :: { Error , Result , Version } ;
44use core:: fmt;
55use der:: {
6- Decode , DecodeValue , Encode , EncodeValue , FixedTag , Header , Length , Reader , Sequence , TagMode ,
7- TagNumber , Writer ,
8- asn1:: { AnyRef , BitStringRef , ContextSpecific , OctetStringRef , SequenceRef } ,
6+ Decode , DecodeValue , DerOrd , Encode , EncodeValue , FixedTag , Header , Length , Reader , Sequence ,
7+ TagMode , TagNumber , Writer ,
8+ asn1:: { AnyRef , BitStringRef , ContextSpecific , OctetStringRef , SetOfRef } ,
99} ;
1010use spki:: AlgorithmIdentifier ;
11+ use x509_cert:: attr:: Attribute ;
1112
1213#[ cfg( feature = "alloc" ) ]
1314use der:: {
1415 SecretDocument ,
15- asn1:: { Any , BitString , OctetString } ,
16+ asn1:: { Any , BitString , OctetString , SetOfVec } ,
1617} ;
1718
1819#[ cfg( feature = "encryption" ) ]
@@ -94,7 +95,7 @@ const PUBLIC_KEY_TAG: TagNumber = TagNumber(1);
9495/// [RFC 5208 Section 5]: https://tools.ietf.org/html/rfc5208#section-5
9596/// [RFC 5958 Section 2]: https://datatracker.ietf.org/doc/html/rfc5958#section-2
9697#[ derive( Clone ) ]
97- pub struct PrivateKeyInfo < Params , Key , PubKey > {
98+ pub struct PrivateKeyInfo < Params , Key , PubKey , Attr > {
9899 /// X.509 `AlgorithmIdentifier` for the private key type.
99100 pub algorithm : AlgorithmIdentifier < Params > ,
100101
@@ -103,9 +104,12 @@ pub struct PrivateKeyInfo<Params, Key, PubKey> {
103104
104105 /// Public key data, optionally available if version is V2.
105106 pub public_key : Option < PubKey > ,
107+
108+ /// Attributes
109+ pub attributes : Option < Attr > ,
106110}
107111
108- impl < Params , Key , PubKey > PrivateKeyInfo < Params , Key , PubKey > {
112+ impl < Params , Key , PubKey , Attr > PrivateKeyInfo < Params , Key , PubKey , Attr > {
109113 /// Create a new PKCS#8 [`PrivateKeyInfo`] message.
110114 ///
111115 /// This is a helper method which initializes `attributes` and `public_key`
@@ -115,6 +119,7 @@ impl<Params, Key, PubKey> PrivateKeyInfo<Params, Key, PubKey> {
115119 algorithm,
116120 private_key,
117121 public_key : None ,
122+ attributes : None ,
118123 }
119124 }
120125
@@ -130,13 +135,15 @@ impl<Params, Key, PubKey> PrivateKeyInfo<Params, Key, PubKey> {
130135 }
131136}
132137
133- impl < ' a , Params , Key , PubKey > PrivateKeyInfo < Params , Key , PubKey >
138+ impl < ' a , Params , Key , PubKey , Attr > PrivateKeyInfo < Params , Key , PubKey , Attr >
134139where
135140 Params : der:: Choice < ' a , Error = der:: Error > + Encode ,
136141 Key : DecodeValue < ' a , Error = der:: Error > + FixedTag + ' a ,
137142 Key : EncodeValue ,
138143 PubKey : DecodeValue < ' a , Error = der:: Error > + FixedTag + ' a ,
139144 PubKey : BitStringLike ,
145+ Attr : DecodeValue < ' a , Error = der:: Error > + FixedTag + SetOfLike < ' a > + ' a ,
146+ Attr :: Item : Clone + Decode < ' a > + DerOrd + Encode ,
140147{
141148 /// Encrypt this private key using a symmetric encryption key derived
142149 /// from the provided password.
@@ -170,7 +177,7 @@ where
170177 }
171178}
172179
173- impl < ' a , Params , Key , PubKey > PrivateKeyInfo < Params , Key , PubKey >
180+ impl < ' a , Params , Key , PubKey , Attr > PrivateKeyInfo < Params , Key , PubKey , Attr >
174181where
175182 Params : der:: Choice < ' a > + Encode ,
176183 PubKey : BitStringLike ,
@@ -188,11 +195,30 @@ where
188195 }
189196}
190197
191- impl < ' a , Params , Key , PubKey > DecodeValue < ' a > for PrivateKeyInfo < Params , Key , PubKey >
198+ impl < ' a , Params , Key , PubKey , Attr > PrivateKeyInfo < Params , Key , PubKey , Attr >
199+ where
200+ Params : der:: Choice < ' a > + Encode ,
201+ Attr : SetOfLike < ' a > ,
202+ {
203+ /// Get a `SET OF` representation of the attributes, if present.
204+ fn attributes_string ( & self ) -> Option < ContextSpecific < SetOfRef < ' a , Attr :: Item > > > {
205+ self . attributes . as_ref ( ) . map ( |attributes| {
206+ let value = attributes. as_set_of ( ) ;
207+ ContextSpecific {
208+ tag_number : ATTRIBUTES_TAG ,
209+ tag_mode : TagMode :: Implicit ,
210+ value,
211+ }
212+ } )
213+ }
214+ }
215+
216+ impl < ' a , Params , Key , PubKey , Attr > DecodeValue < ' a > for PrivateKeyInfo < Params , Key , PubKey , Attr >
192217where
193218 Params : der:: Choice < ' a , Error = der:: Error > + Encode ,
194219 Key : DecodeValue < ' a , Error = der:: Error > + FixedTag + ' a ,
195220 PubKey : DecodeValue < ' a , Error = der:: Error > + FixedTag + ' a ,
221+ Attr : DecodeValue < ' a , Error = der:: Error > + FixedTag + ' a ,
196222{
197223 type Error = der:: Error ;
198224
@@ -202,8 +228,7 @@ where
202228 let algorithm = reader. decode ( ) ?;
203229 let private_key = Key :: decode ( reader) ?;
204230
205- let _attributes =
206- reader. context_specific :: < & SequenceRef > ( ATTRIBUTES_TAG , TagMode :: Implicit ) ?;
231+ let attributes = reader. context_specific :: < Attr > ( ATTRIBUTES_TAG , TagMode :: Implicit ) ?;
207232
208233 let public_key = reader. context_specific :: < PubKey > ( PUBLIC_KEY_TAG , TagMode :: Implicit ) ?;
209234
@@ -226,49 +251,58 @@ where
226251 algorithm,
227252 private_key,
228253 public_key,
254+ attributes,
229255 } )
230256 }
231257}
232258
233- impl < ' a , Params , Key , PubKey > EncodeValue for PrivateKeyInfo < Params , Key , PubKey >
259+ impl < ' a , Params , Key , PubKey , Attr > EncodeValue for PrivateKeyInfo < Params , Key , PubKey , Attr >
234260where
235261 Params : der:: Choice < ' a , Error = der:: Error > + Encode ,
236262 Key : EncodeValue + FixedTag ,
237263 PubKey : BitStringLike ,
264+ Attr : SetOfLike < ' a > ,
265+ Attr :: Item : Clone + Decode < ' a > + DerOrd + Encode ,
238266{
239267 fn value_len ( & self ) -> der:: Result < Length > {
240268 self . version ( ) . encoded_len ( ) ?
241269 + self . algorithm . encoded_len ( ) ?
242270 + self . private_key . encoded_len ( ) ?
271+ + self . attributes_string ( ) . encoded_len ( ) ?
243272 + self . public_key_bit_string ( ) . encoded_len ( ) ?
244273 }
245274
246275 fn encode_value ( & self , writer : & mut impl Writer ) -> der:: Result < ( ) > {
247276 self . version ( ) . encode ( writer) ?;
248277 self . algorithm . encode ( writer) ?;
249278 self . private_key . encode ( writer) ?;
279+ self . attributes_string ( ) . encode ( writer) ?;
250280 self . public_key_bit_string ( ) . encode ( writer) ?;
251281 Ok ( ( ) )
252282 }
253283}
254284
255- impl < ' a , Params , Key , PubKey > Sequence < ' a > for PrivateKeyInfo < Params , Key , PubKey >
285+ impl < ' a , Params , Key , PubKey , Attr > Sequence < ' a > for PrivateKeyInfo < Params , Key , PubKey , Attr >
256286where
257287 Params : der:: Choice < ' a , Error = der:: Error > + Encode ,
258288 Key : DecodeValue < ' a , Error = der:: Error > + FixedTag + ' a ,
259289 Key : EncodeValue ,
260290 PubKey : DecodeValue < ' a , Error = der:: Error > + FixedTag + ' a ,
261291 PubKey : BitStringLike ,
292+ Attr : DecodeValue < ' a , Error = der:: Error > + FixedTag + SetOfLike < ' a > + ' a ,
293+ Attr :: Item : Clone + Decode < ' a > + DerOrd + Encode ,
262294{
263295}
264296
265- impl < ' a , Params , Key , PubKey > TryFrom < & ' a [ u8 ] > for PrivateKeyInfo < Params , Key , PubKey >
297+ impl < ' a , Params , Key , PubKey , Attr > TryFrom < & ' a [ u8 ] > for PrivateKeyInfo < Params , Key , PubKey , Attr >
266298where
267299 Params : der:: Choice < ' a , Error = der:: Error > + Encode ,
268300 Key : DecodeValue < ' a , Error = der:: Error > + FixedTag + ' a ,
269301 Key : EncodeValue ,
270302 PubKey : DecodeValue < ' a , Error = der:: Error > + FixedTag + ' a ,
271303 PubKey : BitStringLike ,
304+ Attr : DecodeValue < ' a , Error = der:: Error > + FixedTag + SetOfLike < ' a > + ' a ,
305+ Attr :: Item : Clone + Decode < ' a > + DerOrd + Encode ,
272306{
273307 type Error = Error ;
274308
@@ -277,63 +311,72 @@ where
277311 }
278312}
279313
280- impl < Params , Key , PubKey > fmt:: Debug for PrivateKeyInfo < Params , Key , PubKey >
314+ impl < Params , Key , PubKey , Attr > fmt:: Debug for PrivateKeyInfo < Params , Key , PubKey , Attr >
281315where
282316 Params : fmt:: Debug ,
283317 PubKey : fmt:: Debug ,
318+ Attr : fmt:: Debug ,
284319{
285320 fn fmt ( & self , f : & mut fmt:: Formatter < ' _ > ) -> fmt:: Result {
286321 f. debug_struct ( "PrivateKeyInfo" )
287322 . field ( "version" , & self . version ( ) )
288323 . field ( "algorithm" , & self . algorithm )
324+ . field ( "Attributes" , & self . attributes )
289325 . field ( "public_key" , & self . public_key )
290326 . finish_non_exhaustive ( )
291327 }
292328}
293329
294330#[ cfg( feature = "alloc" ) ]
295- impl < ' a , Params , Key , PubKey > TryFrom < PrivateKeyInfo < Params , Key , PubKey > > for SecretDocument
331+ impl < ' a , Params , Key , PubKey , Attr > TryFrom < PrivateKeyInfo < Params , Key , PubKey , Attr > >
332+ for SecretDocument
296333where
297334 Params : der:: Choice < ' a , Error = der:: Error > + Encode ,
298335 Key : DecodeValue < ' a , Error = der:: Error > + FixedTag + ' a ,
299336 Key : EncodeValue ,
300337 PubKey : DecodeValue < ' a , Error = der:: Error > + FixedTag + ' a ,
301338 PubKey : BitStringLike ,
339+ Attr : DecodeValue < ' a , Error = der:: Error > + FixedTag + SetOfLike < ' a > + ' a ,
340+ Attr :: Item : Clone + Decode < ' a > + DerOrd + Encode ,
302341{
303342 type Error = Error ;
304343
305- fn try_from ( private_key : PrivateKeyInfo < Params , Key , PubKey > ) -> Result < SecretDocument > {
344+ fn try_from ( private_key : PrivateKeyInfo < Params , Key , PubKey , Attr > ) -> Result < SecretDocument > {
306345 SecretDocument :: try_from ( & private_key)
307346 }
308347}
309348
310349#[ cfg( feature = "alloc" ) ]
311- impl < ' a , Params , Key , PubKey > TryFrom < & PrivateKeyInfo < Params , Key , PubKey > > for SecretDocument
350+ impl < ' a , Params , Key , PubKey , Attr > TryFrom < & PrivateKeyInfo < Params , Key , PubKey , Attr > >
351+ for SecretDocument
312352where
313353 Params : der:: Choice < ' a , Error = der:: Error > + Encode ,
314354 Key : DecodeValue < ' a , Error = der:: Error > + FixedTag + ' a ,
315355 Key : EncodeValue ,
316356 PubKey : DecodeValue < ' a , Error = der:: Error > + FixedTag + ' a ,
317357 PubKey : BitStringLike ,
358+ Attr : DecodeValue < ' a , Error = der:: Error > + FixedTag + SetOfLike < ' a > + ' a ,
359+ Attr :: Item : Clone + Decode < ' a > + DerOrd + Encode ,
318360{
319361 type Error = Error ;
320362
321- fn try_from ( private_key : & PrivateKeyInfo < Params , Key , PubKey > ) -> Result < SecretDocument > {
363+ fn try_from ( private_key : & PrivateKeyInfo < Params , Key , PubKey , Attr > ) -> Result < SecretDocument > {
322364 Ok ( Self :: encode_msg ( private_key) ?)
323365 }
324366}
325367
326368#[ cfg( feature = "pem" ) ]
327- impl < Params , Key , PubKey > PemLabel for PrivateKeyInfo < Params , Key , PubKey > {
369+ impl < Params , Key , PubKey , Attr > PemLabel for PrivateKeyInfo < Params , Key , PubKey , Attr > {
328370 const PEM_LABEL : & ' static str = "PRIVATE KEY" ;
329371}
330372
331373#[ cfg( feature = "subtle" ) ]
332- impl < Params , Key , PubKey > ConstantTimeEq for PrivateKeyInfo < Params , Key , PubKey >
374+ impl < Params , Key , PubKey , Attr > ConstantTimeEq for PrivateKeyInfo < Params , Key , PubKey , Attr >
333375where
334376 Params : Eq ,
335377 Key : PartialEq + AsRef < [ u8 ] > ,
336378 PubKey : PartialEq ,
379+ Attr : PartialEq ,
337380{
338381 fn ct_eq ( & self , other : & Self ) -> Choice {
339382 // NOTE: public fields are not compared in constant time
@@ -346,32 +389,35 @@ where
346389}
347390
348391#[ cfg( feature = "subtle" ) ]
349- impl < Params , Key , PubKey > Eq for PrivateKeyInfo < Params , Key , PubKey >
392+ impl < Params , Key , PubKey , Attr > Eq for PrivateKeyInfo < Params , Key , PubKey , Attr >
350393where
351394 Params : Eq ,
352395 Key : AsRef < [ u8 ] > + Eq ,
353396 PubKey : Eq ,
397+ Attr : Eq ,
354398{
355399}
356400
357401#[ cfg( feature = "subtle" ) ]
358- impl < Params , Key , PubKey > PartialEq for PrivateKeyInfo < Params , Key , PubKey >
402+ impl < Params , Key , PubKey , Attr > PartialEq for PrivateKeyInfo < Params , Key , PubKey , Attr >
359403where
360404 Params : Eq ,
361405 Key : PartialEq + AsRef < [ u8 ] > ,
362406 PubKey : PartialEq ,
407+ Attr : PartialEq ,
363408{
364409 fn eq ( & self , other : & Self ) -> bool {
365410 self . ct_eq ( other) . into ( )
366411 }
367412}
368413
369414/// [`PrivateKeyInfo`] with [`AnyRef`] algorithm parameters, and `&[u8]` key.
370- pub type PrivateKeyInfoRef < ' a > = PrivateKeyInfo < AnyRef < ' a > , & ' a OctetStringRef , BitStringRef < ' a > > ;
415+ pub type PrivateKeyInfoRef < ' a > =
416+ PrivateKeyInfo < AnyRef < ' a > , & ' a OctetStringRef , BitStringRef < ' a > , SetOfRef < ' a , Attribute > > ;
371417
372418/// [`PrivateKeyInfo`] with [`Any`] algorithm parameters, and `Box<[u8]>` key.
373419#[ cfg( feature = "alloc" ) ]
374- pub type PrivateKeyInfoOwned = PrivateKeyInfo < Any , OctetString , BitString > ;
420+ pub type PrivateKeyInfoOwned = PrivateKeyInfo < Any , OctetString , BitString , SetOfVec < Attribute > > ;
375421
376422/// [`BitStringLike`] marks object that will act like a BitString.
377423///
@@ -386,6 +432,22 @@ impl BitStringLike for BitStringRef<'_> {
386432 }
387433}
388434
435+ pub trait SetOfLike < ' a > {
436+ type Item : Clone + DerOrd + Encode ;
437+ fn as_set_of ( & self ) -> SetOfRef < ' a , Self :: Item > ;
438+ }
439+
440+ impl < ' a , T > SetOfLike < ' a > for SetOfRef < ' a , T >
441+ where
442+ T : Clone + DerOrd + Encode ,
443+ {
444+ type Item = T ;
445+
446+ fn as_set_of ( & self ) -> SetOfRef < ' a , T > {
447+ SetOfRef :: from ( self )
448+ }
449+ }
450+
389451#[ cfg( feature = "alloc" ) ]
390452mod allocating {
391453 use super :: * ;
@@ -399,13 +461,25 @@ mod allocating {
399461 }
400462 }
401463
464+ impl < ' a , T > SetOfLike < ' a > for & ' a SetOfVec < T >
465+ where
466+ T : Clone + DerOrd + Encode + ' a ,
467+ {
468+ type Item = T ;
469+
470+ fn as_set_of ( & self ) -> SetOfRef < ' a , T > {
471+ self . owned_to_ref ( )
472+ }
473+ }
474+
402475 impl < ' a > RefToOwned < ' a > for PrivateKeyInfoRef < ' a > {
403476 type Owned = PrivateKeyInfoOwned ;
404477 fn ref_to_owned ( & self ) -> Self :: Owned {
405478 PrivateKeyInfoOwned {
406479 algorithm : self . algorithm . ref_to_owned ( ) ,
407480 private_key : self . private_key . to_owned ( ) ,
408481 public_key : self . public_key . ref_to_owned ( ) ,
482+ attributes : self . attributes . ref_to_owned ( ) ,
409483 }
410484 }
411485 }
@@ -417,6 +491,7 @@ mod allocating {
417491 algorithm : self . algorithm . owned_to_ref ( ) ,
418492 private_key : self . private_key . borrow ( ) ,
419493 public_key : self . public_key . owned_to_ref ( ) ,
494+ attributes : self . attributes . owned_to_ref ( ) ,
420495 }
421496 }
422497 }
0 commit comments