// X509CRL.cs: Handles X.509 certificates revocation lists.
//
// Author:
-// Sebastien Pouliot <sebastien@ximian.com>
+// Sebastien Pouliot <sebastien@xamarin.com>
//
-// (C) 2004 Novell (http://www.novell.com)
-//
-
+// Copyright (C) 2004,2006 Novell Inc. (http://www.novell.com)
+// Copyright 2013 Xamarin Inc. (http://www.xamarin.com)
//
// Permission is hereby granted, free of charge, to any person obtaining
// a copy of this software and associated documentation files (the
using System.IO;
using System.Security.Cryptography;
+using Mono.Security.Cryptography;
using Mono.Security.X509.Extensions;
namespace Mono.Security.X509 {
* crlExtensions [0] Extensions OPTIONAL }
* -- if present, MUST be v2
*/
-#if INSIDE_CORLIB
- internal
-#else
+#if !INSIDE_CORLIB
public
#endif
class X509Crl {
private byte[] signature;
private X509ExtensionCollection extensions;
private byte[] encoded;
+ private byte[] hash_value;
public X509Crl (byte[] crl)
{
// CertificateList / TBSCertList / revokedCertificates SEQUENCE OF SEQUENCE {
entries = new ArrayList ();
// this is OPTIONAL so it may not be present if no entries exists
- if (next.Tag == 0x30) {
+ if ((next != null) && (next.Tag == 0x30)) {
ASN1 revokedCertificates = next;
for (int i=0; i < revokedCertificates.Count; i++) {
entries.Add (new X509CrlEntry (revokedCertificates [i]));
get { return extensions; }
}
+ public byte[] Hash {
+ get {
+ if (hash_value == null) {
+ ASN1 encodedCRL = new ASN1 (encoded);
+ byte[] toBeSigned = encodedCRL [0].GetBytes ();
+ using (var ha = PKCS1.CreateFromOid (signatureOID))
+ hash_value = ha.ComputeHash (toBeSigned);
+ }
+ return hash_value;
+ }
+ }
+
public string IssuerName {
get { return issuer; }
}
}
}
+ public byte[] RawData {
+ get { return (byte[]) encoded.Clone (); }
+ }
+
public byte Version {
get { return version; }
}
// 1. x509 certificate must be a CA certificate (unknown for v1 or v2 certs)
if (x509.Version >= 3) {
- // 1.1. Check for "cRLSign" bit in KeyUsage extension
- X509Extension ext = x509.Extensions ["2.5.29.15"];
- if (ext != null) {
- KeyUsageExtension keyUsage = new KeyUsageExtension (ext);
- if (!keyUsage.Support (KeyUsages.cRLSign))
- return false;
- }
+ BasicConstraintsExtension basicConstraints = null;
// 1.2. Check for ca = true in BasicConstraint
- ext = x509.Extensions ["2.5.29.19"];
+ X509Extension ext = x509.Extensions ["2.5.29.19"];
if (ext != null) {
- BasicConstraintsExtension basicConstraints = new BasicConstraintsExtension (ext);
+ basicConstraints = new BasicConstraintsExtension (ext);
if (!basicConstraints.CertificateAuthority)
return false;
}
+ // 1.1. Check for "cRLSign" bit in KeyUsage extension
+ ext = x509.Extensions ["2.5.29.15"];
+ if (ext != null) {
+ KeyUsageExtension keyUsage = new KeyUsageExtension (ext);
+ if (!keyUsage.Support (KeyUsages.cRLSign)) {
+ // 2nd chance if basicConstraints is CertificateAuthority
+ // and KeyUsage support digitalSignature
+ if ((basicConstraints == null) || !keyUsage.Support (KeyUsages.digitalSignature))
+ return false;
+ }
+ }
}
// 2. CRL issuer must match CA subject name
if (issuer != x509.SubjectName)
}
}
- private byte[] GetHash (string hashName)
- {
- ASN1 encodedCRL = new ASN1 (encoded);
- byte[] toBeSigned = encodedCRL [0].GetBytes ();
- HashAlgorithm ha = HashAlgorithm.Create (hashName);
- return ha.ComputeHash (toBeSigned);
- }
-
internal bool VerifySignature (DSA dsa)
{
if (signatureOID != "1.2.840.10040.4.3")
throw new CryptographicException ("Unsupported hash algorithm: " + signatureOID);
DSASignatureDeformatter v = new DSASignatureDeformatter (dsa);
// only SHA-1 is supported
- string hashName = "SHA1";
- v.SetHashAlgorithm (hashName);
+ v.SetHashAlgorithm ("SHA1");
ASN1 sign = new ASN1 (signature);
if ((sign == null) || (sign.Count != 2))
return false;
byte[] part1 = sign [0].Value;
byte[] part2 = sign [1].Value;
byte[] sig = new byte [40];
- Buffer.BlockCopy (part1, 0, sig, (20 - part1.Length), part1.Length);
- Buffer.BlockCopy (part2, 0, sig, (40 - part2.Length), part2.Length);
- return v.VerifySignature (GetHash (hashName), sig);
+ // parts may be less than 20 bytes (i.e. first bytes were 0x00)
+ // parts may be more than 20 bytes (i.e. first byte > 0x80, negative)
+ int s1 = System.Math.Max (0, part1.Length - 20);
+ int e1 = System.Math.Max (0, 20 - part1.Length);
+ Buffer.BlockCopy (part1, s1, sig, e1, part1.Length - s1);
+ int s2 = System.Math.Max (0, part2.Length - 20);
+ int e2 = System.Math.Max (20, 40 - part2.Length);
+ Buffer.BlockCopy (part2, s2, sig, e2, part2.Length - s2);
+ return v.VerifySignature (Hash, sig);
}
internal bool VerifySignature (RSA rsa)
{
RSAPKCS1SignatureDeformatter v = new RSAPKCS1SignatureDeformatter (rsa);
- string hashName = null;
- switch (signatureOID) {
- // MD2 with RSA encryption
- case "1.2.840.113549.1.1.2":
- // maybe someone installed MD2 ?
- hashName = "MD2";
- break;
- // MD5 with RSA encryption
- case "1.2.840.113549.1.1.4":
- hashName = "MD5";
- break;
- // SHA-1 with RSA Encryption
- case "1.2.840.113549.1.1.5":
- hashName = "SHA1";
- break;
- default:
- throw new CryptographicException ("Unsupported hash algorithm: " + signatureOID);
- }
- v.SetHashAlgorithm (hashName);
- return v.VerifySignature (GetHash (hashName), signature);
+ v.SetHashAlgorithm (PKCS1.HashNameFromOid (signatureOID));
+ return v.VerifySignature (Hash, signature);
}
public bool VerifySignature (AsymmetricAlgorithm aa)