Clover Coverage Report
Coverage timestamp: Sun Mar 23 2008 08:24:39 GMT
63   497   12   2.74
14   136   0.54   23
23     1.48  
1    
 
 
  AttributeCertificate       Line # 117 63 12 61% 0.61
 
  (1)
 
1    /*
2    * Copyright (c) 2000-2005, University of Salford
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions are met:
7    *
8    * Redistributions of source code must retain the above copyright notice, this
9    * list of conditions and the following disclaimer.
10    *
11    * Redistributions in binary form must reproduce the above copyright notice,
12    * this list of conditions and the following disclaimer in the documentation
13    * and/or other materials provided with the distribution.
14    *
15    * Neither the name of the University of Salford nor the names of its
16    * contributors may be used to endorse or promote products derived from this
17    * software without specific prior written permission.
18    *
19    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20    * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21    * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22    * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23    * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24    * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25    * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26    * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27    * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28    * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29    * POSSIBILITY OF SUCH DAMAGE.
30    */
31    /*
32    * Copyright (c) 2006, University of Kent
33    * All rights reserved.
34    *
35    * Redistribution and use in source and binary forms, with or without
36    * modification, are permitted provided that the following conditions are met:
37    *
38    * Redistributions of source code must retain the above copyright notice, this
39    * list of conditions and the following disclaimer.
40    *
41    * Redistributions in binary form must reproduce the above copyright notice,
42    * this list of conditions and the following disclaimer in the documentation
43    * and/or other materials provided with the distribution.
44    *
45    * 1. Neither the name of the University of Kent nor the names of its
46    * contributors may be used to endorse or promote products derived from this
47    * software without specific prior written permission.
48    *
49    * 2. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
50    * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
51    * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
52    * PURPOSE ARE DISCLAIMED.
53    *
54    * 3. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
55    * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
56    * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
57    * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
58    * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
59    * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
60    * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
61    * POSSIBILITY OF SUCH DAMAGE.
62    *
63    * 4. YOU AGREE THAT THE EXCLUSIONS IN PARAGRAPHS 2 AND 3 ABOVE ARE REASONABLE
64    * IN THE CIRCUMSTANCES. IN PARTICULAR, YOU ACKNOWLEDGE (1) THAT THIS
65    * SOFTWARE HAS BEEN MADE AVAILABLE TO YOU FREE OF CHARGE, (2) THAT THIS
66    * SOFTWARE IS NOT "PRODUCT" QUALITY, BUT HAS BEEN PRODUCED BY A RESEARCH
67    * GROUP WHO DESIRE TO MAKE THIS SOFTWARE FREELY AVAILABLE TO PEOPLE WHO WISH
68    * TO USE IT, AND (3) THAT BECAUSE THIS SOFTWARE IS NOT OF "PRODUCT" QUALITY
69    * IT IS INEVITABLE THAT THERE WILL BE BUGS AND ERRORS, AND POSSIBLY MORE
70    * SERIOUS FAULTS, IN THIS SOFTWARE.
71    *
72    * 5. This license is governed, except to the extent that local laws
73    * necessarily apply, by the laws of England and Wales.
74    */
75   
76    package issrg.ac;
77   
78    import issrg.pba.RawCredential;
79   
80    import org.apache.log4j.*;
81   
82    import iaik.asn1.*;
83    import iaik.asn1.structures.*;
84   
85    /**
86    * This is the class representing AttributeCertificate ASN.1 construct as per
87    * X.509(2000) draft v6. All other constructs are taken from it as well.
88    *
89    * <p>According to various versions of the draft, there can be ACs with explicit
90    * and implicit BER encoding. This class and all of its components are designed
91    * to support the difference.
92    *
93    * <p>This implementation extensively uses IAIK ASN.1 classes, so you may need
94    * to know their documentation before you can use or update the AC classes
95    * provided.
96    *
97    * <p>Note that all of the components are validating encoders and decoders and
98    * throw exceptions if the values specified are unacceptable (invalid BER
99    * encoding, unacceptable combination of values, etc
100    * checking syntax). However, it is your responsibility to verify that the AC
101    * includes only features
102    * allowed by the version specified (checking semantics).
103    *
104    * <p>The classes can decode any Attributes and Extensions. However, to
105    * automatically create the objects representing the specific attribute values
106    * or extensions, you need to register the object extending AttributeValue or
107    * Extension, using Attribute.registerAttribute(String, Class) or
108    * Extensions.registerExtension(String, Class) method respectively. In this way
109    * the instances of the corresponding classes will be created directly during
110    * the decoding process. If an unknown attribute or extension is encountered,
111    * the value will remain a generic AttributeValue or Extension respectively,
112    * and should be decoded by your code.
113    *
114    * @see Attribute.registerAttribute(String,Class), Extensions.registerExtension(String,Class)
115    */
116   
 
117    public class AttributeCertificate implements iaik.asn1.ASN1Type, Cloneable{
118   
119    private static Logger logger = Logger.getLogger(AttributeCertificate.class);
120    /**
121    * This value specifies whether implicit or explicit tagging should be
122    * used when performing BER encoding or decoding.
123    *
124    * <p>This value is being referred to by all ASN.1 objects when delivering
125    * toASN1Object result. By default
126    * it is set to true.
127    *
128    * <p>External code should not rely on this value while the AC is being
129    * decoded, when guessEncoding method is used.
130    */
131    protected static boolean USE_IMPLICIT_ENCODING=true;
132   
133    /**
134    * Returns true if Implicit encoding of tags will be used. Note that the flag
135    * is static and
136    * affects all instances of AttributeCertificate.
137    */
 
138  0 toggle public static boolean isImplicit(){
139  0 return USE_IMPLICIT_ENCODING;
140    }
141   
142    protected AttributeCertificateInfo acinfo = new AttributeCertificateInfo();
143   
144    /**
145    * Returns the ACInfo component of the AC.
146    *
147    * @return AttributeCertificateInfo with the content of the Attribute
148    * Certificate
149    */
 
150  17973 toggle public AttributeCertificateInfo getACInfo(){
151  17973 return acinfo;
152    }
153   
154    /**
155    * Sets the ACInfo component of the AC.
156    *
157    * @param acinfo - the AttributeCertificateInfo with the contents of the
158    * AC
159    */
 
160  0 toggle public void setACInfo(AttributeCertificateInfo acinfo){
161  0 this.acinfo=acinfo;
162    }
163   
164    protected AlgorithmID signatureAlgorithm = new AlgorithmID(); // Algorithm Identifier
165   
166    /**
167    * Returns the SignatureAlgorithm component of the AC.
168    *
169    * @return AlgorithmID of the algorithm used to sign the AC
170    */
 
171  1788 toggle public AlgorithmID getSignatureAlgorithm(){
172  1788 return signatureAlgorithm;
173    }
174   
175    /**
176    * Sets the SignatureAlgorithm component of the AC. You should make sure that
177    * this is the same as in AttributeCertificateInfo.
178    *
179    * @param signatureAlgorithm - the AlgorithmID of the algorithm used to sign
180    * the AC
181    */
 
182  0 toggle public void setSignatureAlgorithm(AlgorithmID signatureAlgorithm){
183  0 this.signatureAlgorithm=signatureAlgorithm;
184    }
185   
186    protected BIT_STRING signatureValue = new BIT_STRING("0");
187   
188    /**
189    * Returns the SignatureValue component of the AC.
190    *
191    * @return BIT_STRING of the signature
192    */
 
193  1788 toggle public BIT_STRING getSignatureValue(){
194  1788 return signatureValue;
195    }
196   
197    /**
198    * Sets the SignatureValue component of the AC.
199    *
200    * @param signatureValue - the BIT_STRING containing the signature bytes
201    */
 
202  0 toggle public void setSignatureValue(BIT_STRING signatureValue){
203  0 this.signatureValue=signatureValue;
204    }
205   
206    /**
207    * The constructor is protected, because you shouldn't really be able to
208    * create empty ACs.
209    */
 
210  0 toggle protected AttributeCertificate() {
211    }
212   
213    /**
214    * This constructor decodes the X.509 AC from the given ASN1Object.
215    *
216    * @param ao - the parsed ASN.1 structure
217    * @throws CodingException, if the ASN.1 does not represent a valid X.509 AC
218    * construct
219    */
 
220  2979 toggle public AttributeCertificate(ASN1Object ao) throws CodingException{
221  2979 decode(ao);
222    }
223   
224    /**
225    * This constructor copies the given AttributeCertificate
226    *
227    * @param ac - the Attribute Certificate to copy
228    * @throws CodingException, if there was a problem when copying the AC
229    */
 
230  0 toggle public AttributeCertificate(AttributeCertificate ac) throws CodingException{
231   
232  0 acinfo = new AttributeCertificateInfo(ac.acinfo);
233  0 signatureAlgorithm = new AlgorithmID(ac.signatureAlgorithm.getAlgorithm(), ac.signatureAlgorithm.getParameter());
234  0 signatureValue = new BIT_STRING(ac.signatureValue.getBinaryString());
235    }
236   
237    /**
238    * This constructor builds the Attribute Certificate out of its components.
239    * It is your responsibility to make sure that the signature algorithm is the
240    * same as inside AttributeCertificateInfo, and that the signature is computed
241    * over the BER encoding of the same AttributeCertificateInfo, encoded using
242    * IAIK library. Note that if you compute the signature using an encoding
243    * produced by a different library, the signature may not validate since there
244    * are multiple valid BER encodings and different libraries may produce
245    * different binary for the same ASN.1 construct.
246    *
247    * @param aci - the AttributeCertificateInfo with the contents of the X.509
248    * Attribute Certificate
249    * @param sa - the AlgorithmID of the signature algorithm used to sign the
250    * X.509 Attribute Certificate
251    * @param sv - the BIT_STRING of the signature
252    */
 
253  20 toggle public AttributeCertificate(AttributeCertificateInfo aci, AlgorithmID sa, BIT_STRING sv){
254   
255  20 acinfo = aci;
256  20 signatureAlgorithm = sa;
257  20 signatureValue = sv;
258    }
259   
260    /**
261    * This method generates a ASN1Object. It can be encoded as BER
262    * using IAIK library.
263    *
264    * @return ASN1Object that is the X.509 AC construct
265    * @throws CodingException if there was an error encoding the AC
266    */
 
267  22 toggle public ASN1Object toASN1Object() throws CodingException{
268  22 ASN1Object result = new SEQUENCE();
269   
270  22 result.addComponent(acinfo.toASN1Object());
271  22 result.addComponent(signatureAlgorithm.toASN1Object());
272  22 result.addComponent(signatureValue);
273   
274  22 return result;
275    }
276   
277    /**
278    * This method decodes X.509 Attribute Certificate from a given ASN1Object
279    * construct. This object will represent the AC that has been decoded.
280    *
281    * @param ao - the ASN1Object, as decoded by IAIK library
282    * @throws CodingException if the provided ASN1Object is not a v1 or v2 X.509
283    * Attribute Certificate
284    */
 
285  2979 toggle public void decode(ASN1Object ao) throws CodingException{
286  2979 if (!ao.isA(ASN.SEQUENCE)){
287  0 throw new CodingException("AttributeCertificate SEQUENCE tag was expected");
288    }
289   
290  2979 if (ao.countComponents()!=3){
291  0 throw new CodingException("Illegal number of entries in AttributeCertificate tag: "+Integer.toString(ao.countComponents()));
292    }
293   
294  2979 acinfo = new AttributeCertificateInfo(ao.getComponentAt(0));
295  1859 signatureAlgorithm = new AlgorithmID(ao.getComponentAt(1));
296  1859 signatureValue = (BIT_STRING)ao.getComponentAt(2);
297    }
298   
299    /**
300    * This method generates a string representation of the Attribute Certificate.
301    * It will indent structures, so it will look nicer.
302    *
303    * @return the String representation of the AC.
304    */
 
305  4 toggle public String toString(){
306  4 return toString("");
307    }
308   
309    /**
310    * This method will use the specified indent to output the AC text.
311    *
312    * @return the String representation of the AC with the given indent
313    */
 
314  4 toggle public String toString(String ident){
315  4 return "SEQUENCE { -- AttributeCertificate --\n "+ident+
316    "acinfo = "+acinfo.toString(ident+" ")+",\n "+ident+
317    "signatureAlgorithm = "+signatureAlgorithm.toString()+",\n "+ident+
318    "signatureValue = "+signatureValue.getBinaryString()+"\n"+ident+"}";
319    }
320   
321    /**
322    * This method clones the Attribute Certificate. It returns an identical copy
323    * of the Attribute Certificate.
324    *
325    * @return Object that can be cast to AttributeCertificate, or null, if there
326    * was a problem when creating the clone.
327    */
 
328  0 toggle public Object clone(){
329  0 try{
330  0 return new AttributeCertificate(this);
331    }catch (CodingException ex){
332  0 return null;
333    }
334    }
335   
336   
337    /**
338    * This method returns a DER encoded Attribute Certificate so you can store
339    * it onto a disk or LDAP directory.
340    *
341    * @return byte[] filled in with the bytes of the DER encoding
342    *
343    * @throws iaik.asn1.CodingException if an encoding error occurred
344    */
 
345  22 toggle public byte[] getEncoded() throws CodingException {
346  22 return iaik.asn1.DerCoder.encode(toASN1Object());
347    }
348   
349    /**
350    * This method returns a byte array of the ACInfo taken from the BER encoding
351    * of the AC
352    * as is, so you can check the signature.
353    *
354    * <p>This method does not verify that it actually gets the BER encoded AC,
355    * and not just
356    * an arbitrary byte array.
357    *
358    * @param acBytes is the array of bytes of the BER encoded AC
359    *
360    * @return byte array from the acBytes, corresponding to the ACInfo part of
361    * it
362    *
363    * @throws CodingException in some cases when it can detect that the AC is
364    * malformed; note
365    * that proper checks are left to the caller to speed up: the caller may
366    * have constructed
367    * the AttributeCertificate object already
368    */
 
369  1788 toggle public static byte [] getToBeSignedByteArray(byte [] acBytes) throws CodingException {
370  1788 return new iaik.asn1.ASN1(acBytes).getFirstObject();
371    }
372   
373    /**
374    * This method sets the encoding of the AC to be implicit or explicit,
375    * depending on the value.
376    * The encoding will be enforced for all components of the AC after calling
377    * this method.
378    *
379    * <p>Also the value of the flag is used when decoding an AC. If the AC is
380    * encoded with
381    * Explicit encoding, but the flag says to use Implicit encoding, an AC
382    * decoding error
383    * will occur at run-time. It is advised that guessEncoding method is used
384    * to decode
385    * an AC independent of whether it is Implicitly or Explicitly encoded.
386    *
387    * @param implicit specifies if the AC should be encoded implicitly or not
388    */
 
389  0 toggle public static void setImplicitEncoding(boolean implicit){
390  0 USE_IMPLICIT_ENCODING=implicit;
391    }
392   
393    /**
394    * This method lets you decode the byte array independent of the actual
395    * encoding of the
396    * AC in it. It will sequentially attempt to decode using
397    * USE_IMPLICIT_ENCODING flag value,
398    * then, if that fails with an exception, to decode using the opposite value
399    * of the flag.
400    *
401    * <p>Note that the value of the USE_IMPLICIT_ENCODING flag changes during
402    * execution of this
403    * method, so external code should not access the flag while decoding, only
404    * the AC objects should.
405    *
406    * @param ac is the BER encoding of an X.509 Attribute Certificate
407    *
408    * @return issrg.ac.AttributeCertificate object
409    *
410    * @throws CodingException if neither encoding helped to decode the AC
411    */
 
412  1859 toggle public static AttributeCertificate guessEncoding(byte[] ac) throws CodingException{
413   
414  1859 try{
415  1859 return guessEncoding(new java.io.ByteArrayInputStream(ac));
416    }catch (java.io.IOException io){
417  0 throw new CodingException("Error accessing byte array");
418    }
419    }
420   
421    /**
422    * This method allows to parse either byte[] or Base64 encoded ACs (String
423    * must be passed in that case)
424    *
425    * @param ac - the Attribute Certificate, either as a byte array or as a
426    * Base64 String
427    * @return the decoded AttributeCertificate
428    * @throws CodingException, if it is neither implicitly, nor explicitly
429    * encoded Attribute Certificate
430    */
 
431  1790 toggle public static AttributeCertificate guessEncoding(Object ac) throws CodingException {
432  1790 if (ac instanceof byte[]){
433  1790 return guessEncoding((byte[]) ac);
434    }
435   
436  0 if (ac instanceof String){
437  0 try{
438  0 return guessEncoding(new iaik.utils.Base64InputStream(new java.io.ByteArrayInputStream(((String)ac).getBytes())));
439    }catch(java.io.IOException io){
440  0 throw new CodingException("Error accessing Base64 encoding");
441    }
442    }
443   
444  0 if (ac instanceof RawCredential) return guessEncoding(((RawCredential)ac).getCredential());
445  0 throw new CodingException("Unsupported encoding of the AC");
446    }
447   
448    /**
449    * This method does the same as guessEncoding(byte[]), but operates on an
450    * InputStream.
451    *
452    * @param is - the InputStream containing the BER encoded Attribute
453    * Certificate
454    *
455    * @return the decoded AttributeCertificate
456    * @throws CodingException, if it is neither implicitly, nor explicitly
457    * encoded Attribute Certificate
458    */
 
459  1859 toggle public static AttributeCertificate guessEncoding(java.io.InputStream is) throws CodingException, java.io.IOException{
460  1859 boolean b=USE_IMPLICIT_ENCODING;
461  1859 AttributeCertificate result;
462  1859 ASN1Object ao = iaik.asn1.DerCoder.decode(is);
463  1859 try{
464  1859 USE_IMPLICIT_ENCODING=false; // this is a non-destructive approach; Explicit decoders don't change the ASN1Object structure
465  1859 result=new AttributeCertificate(ao);
466    }catch(CodingException ce){
467  1120 USE_IMPLICIT_ENCODING=true;
468  1120 result=new AttributeCertificate(ao);
469    }finally{
470  1859 USE_IMPLICIT_ENCODING=b;
471    }
472   
473  1859 return result;
474    }
475   
476    /**
477    * This is a utility method that returns the holder of the given Attribute
478    * Certificate, or null,
479    * if it is not an Attribute Certificate.
480    *
481    * @param ac - the AttributeCertificate, either as a byte array or a Base64
482    * encoded String
483    * @return String representation of the Holder DN, or null, if it is not
484    * an AC
485    */
 
486  11 toggle public static String getHolderDN(Object ac){
487  11 String result=null;
488   
489  11 try{
490  11 Holder h = guessEncoding(ac).getACInfo().getHolder();
491  11 result = h.getEntityName()==null?null:issrg.ac.Util.generalNamesToString(h.getEntityName());
492  0 if (result==null) result = issrg.ac.Util.issuerSerialToDN(issrg.ac.Util.generalNamesToString(h.getBaseCertificateID().getIssuer()), h.getBaseCertificateID().getSerial());
493    }catch(CodingException ce){}
494   
495  11 return result;
496    }
497    }