Example #1
0
		/// <summary>
		/// Initializes a new <see cref="CertificateChain"/> instance from a <see cref="Certificate"/>.
		/// </summary>
		/// <param name="cert">The certificate for which a chain is being built.</param>
		/// <param name="additional">Any additional store to be searched for supporting certificates and CTLs.</param>
		/// <param name="options">Additional certificate chain options.</param>
		/// <remarks><paramref name="cert"/> will always be the end certificate.</remarks>
		/// <exception cref="ArgumentNullException"><paramref name="cert"/> is a null reference (<b>Nothing</b> in Visual Basic).</exception>
		/// <exception cref="CertificateException">An error occurs while building the certificate chain.</exception>
		public CertificateChain(Certificate cert, CertificateStore additional, CertificateChainOptions options) {
			if (cert == null)
				throw new ArgumentNullException();
			IntPtr addstore = additional == null ? IntPtr.Zero : additional.Handle;
			ChainParameters para = new ChainParameters();
			para.cbSize = Marshal.SizeOf(typeof(ChainParameters));
			para.RequestedUsagecUsageIdentifier = 0;
			para.RequestedUsagedwType = 0;
			para.RequestedUsagergpszUsageIdentifier = IntPtr.Zero;
			if (SspiProvider.CertGetCertificateChain(IntPtr.Zero, cert.Handle, IntPtr.Zero, addstore, ref para, (int)options, IntPtr.Zero, ref m_Handle) == 0)
				throw new CertificateException("Unable to find the certificate chain.");
			m_Certificate = cert;
		}
		/// <summary>
		/// Initializes a new instance of the <see cref="CertificateStoreCollection"/> class.
		/// </summary>
		/// <param name="stores">An array of stores that should be added to the collection.</param>
		/// <exception cref="ArgumentNullException"><paramref name="stores"/> is a null reference (<b>Nothing</b> in Visual Basic).</exception>
		/// <exception cref="ArgumentException">One of the <see cref="CertificateStore"/> objects in the array is a <see cref="CertificateStoreCollection"/> instance. This is not allowed to avoid circular dependencies.</exception>
		/// <exception cref="CertificateException">An error occurs while adding a certificate to the collection.</exception>
		public CertificateStoreCollection(CertificateStore[] stores) : base(SspiProvider.CertOpenStore(new IntPtr(SecurityConstants.CERT_STORE_PROV_COLLECTION), 0, 0, 0, null), false) {
			if (stores == null)
				throw new ArgumentNullException();
			for(int i = 0; i < stores.Length; i++) {
				if (stores[i].ToString() == this.ToString()) {
					// used in order to avoid circular dependencies
					throw new ArgumentException("A certificate store collection cannot hold other certificate store collections.");
				}
			}
			for(int i = 0; i < stores.Length; i++) {
				if (SspiProvider.CertAddStoreToCollection(this.Handle, stores[i].Handle, 0, 0) == 0)
					throw new CertificateException("Could not add the store to the collection.");
			}
			m_Stores = new ArrayList(); // used to hold references to the certificate stores so they cannot be finalized
			m_Stores.AddRange(stores);
		}
Example #3
0
 /// <summary>
 /// Find a server certificate in the given store.
 /// </summary>
 /// <param name="store"></param>
 /// <returns></returns>
 public static Certificate FindServerCert(CertificateStore store)
 {
     // return store.FindCertificate(new string[] {OID_PKIX_KP_SERVER_AUTH});
     return store.FindCertificateByUsage(new string[] {OID_PKIX_KP_SERVER_AUTH});
 }
 protected SslHandshakeStatus ProcessCertificate(HandshakeMessage message, bool client)
 {
     if (client) {
         if (m_State != HandshakeType.ServerHello)
             throw new SslException(AlertDescription.UnexpectedMessage, "Certificate message must be preceded by a ServerHello message.");
     } else { // server
         if (m_State != HandshakeType.ClientHello)
             throw new SslException(AlertDescription.UnexpectedMessage, "Certificate message must be preceded by a ClientHello message.");
     }
     UpdateHashes(message, HashUpdate.All); // input message
     Certificate[] certs = null;
     try {
         certs = ParseCertificateList(message.fragment);
         if (certs.Length == 0) {
             if (!m_MutualAuthentication)
                 return new SslHandshakeStatus(SslStatus.MessageIncomplete, null);
         }
     } catch (SslException t) {
         throw t;
     } catch (Exception f) {
         throw new SslException(f, AlertDescription.InternalError, "The Certificate message is invalid.");
     }
     CertificateChain chain = null;
     m_RemoteCertificate = null;
     if (certs.Length != 0) {
         m_RemoteCertificate = certs[0];
         if (m_RemoteCertificate.GetPublicKeyLength() < 512) {
             throw new SslException(AlertDescription.HandshakeFailure, "The pulic key should be at least 512 bits.");
         }
         CertificateStore cs = new CertificateStore(certs);
         for(int i = 0; i < certs.Length; i++) {
             certs[i].Store = cs;
         }
         chain = new CertificateChain(m_RemoteCertificate, cs);
     }
     VerifyChain(chain, client);
     return new SslHandshakeStatus(SslStatus.MessageIncomplete, null);
 }
Example #5
0
		/// <summary>
		/// Returns a CertificateStore from a list of cached stores. If the store is not yet cached, it will be created first.
		/// </summary>
		/// <param name="name">The name of the store.</param>
		/// <returns>The cached store.</returns>
		internal static CertificateStore GetCachedStore(string name) {
			CertificateStore cs = null;
			lock(m_CachedStores) {
				cs = m_CachedStores[name] as CertificateStore;
				if (cs == null) {
					cs = new CertificateStore(name);
					m_CachedStores.Add(name, cs);
				}
			}
			return cs;
		}
Example #6
0
		/// <summary>
		/// Duplicates an exisiting <see cref="CertificateStore"/>.
		/// </summary>
		/// <param name="store">The store to duplicate.</param>
		/// <exception cref="ArgumentNullException"><paramref name="store"/> is a null reference (<b>Nothing</b> in Visual Basic).</exception>
		public CertificateStore(CertificateStore store) {
			if (store == null)
				throw new ArgumentNullException();
			InitStore(store.m_Handle, true);
		}
 private int TestConstructs()
 {
     CertificateStore cs = null;
     // empty constructor
     try {
         cs = new CertificateStore();
         if (cs.EnumCertificates().Length != 0)
             AddError("CS-TC-1");
     } catch {
         AddError("CS-TC-2");
     }
     // string constructor
     try {
         cs = new CertificateStore((string)null);
         AddError("CS-TC-3");
     } catch (ArgumentNullException) {
     } catch {
         AddError("CS-TC-4");
     }
     try {
         cs = new CertificateStore("ROOT");
         if (cs.EnumCertificates().Length == 0)
             AddError("CS-TC-5"); // it is _very_ unlikely that the ROOT store is empty
     } catch {
         AddError("CS-TC-6");
     }
     // CertificateStore constructor
     try {
         cs = new CertificateStore(cs);
         if (cs.EnumCertificates().Length == 0)
             AddError("CS-TC-7"); //copy of the ROOT store
     } catch {
         AddError("CS-TC-8");
     }
     try {
         cs = new CertificateStore((CertificateStore)null);
         AddError("CS-TC-9");
     } catch (ArgumentNullException) {
     } catch {
         AddError("CS-TC-10");
     }
     // IntPtr constructor
     try {
         cs = new CertificateStore(IntPtr.Zero);
         AddError("CS-TC-11");
     } catch (ArgumentException) {
     } catch {
         AddError("CS-TC-12");
     }
     try {
         cs = new CertificateStore(IntPtr.Zero, true);
         AddError("CS-TC-13");
     } catch (ArgumentException) {
     } catch {
         AddError("CS-TC-14");
     }
     try {
         cs = new CertificateStore(new CertificateStore().Handle, true);
     } catch {
         AddError("CS-TC-15");
     }
     return 15;
 }
Example #8
0
 /// <summary>
 /// Creates an in memory <see cref="CertificateStore"/> with this <see cref="Certificate"/> in it.
 /// </summary>
 /// <param name="withParents"><b>true</b> if the parent certificates should be included [if possible], <b>false</b> otherwise.</param>
 /// <returns>A CertificateStore instance.</returns>
 private CertificateStore CreateCertStore(bool withParents)
 {
     CertificateStore store = new CertificateStore();
     if (withParents) {
         Certificate[] c = this.GetCertificateChain().GetCertificates();
         for (int i = 0; i < c.Length; i++) {
             store.AddCertificate(c[i]);
         }
     } else {
         store.AddCertificate(this);
     }
     return store;
 }
		/// <summary>
		/// Adds a certificate store to the collection.
		/// </summary>
		/// <param name="store">An instance of the <see cref="CertificateStore"/> class.</param>
		/// <exception cref="ArgumentNullException"><paramref name="store"/> is a null reference (<b>Nothing</b> in Visual Basic).</exception>
		/// <exception cref="ArgumentException">The specified certificate store is a <see cref="CertificateStoreCollection"/> instance. This is not allowed to avoid circular dependencies.</exception>
		/// <exception cref="CertificateException">An error occurs while adding the certificate to the collection.</exception>
		public void AddStore(CertificateStore store) {
			if (store == null)
				throw new ArgumentNullException();
			if (store.ToString() == this.ToString()) // avoid circular dependencies
				throw new ArgumentException("A certificate store collection cannot hold other certificate store collections.");
			if (SspiProvider.CertAddStoreToCollection(this.Handle, store.Handle, 0, 0) == 0)
				throw new CertificateException("Could not add the store to the collection.");
			m_Stores.Add(store);
		}
Example #10
0
        /// <summary>
        /// Initializes this <see cref="Certificate"/> instance from a handle.
        /// </summary>
        /// <param name="handle">The handle from which to initialize the state of the new instance.</param>
        /// <param name="duplicate"><b>true</b> if the handle should be duplicated, <b>false</b> otherwise.</param>
        /// <param name="store">The store that owns the certificate.</param>
        /// <exception cref="ArgumentException"><paramref name="handle"/> is invalid.</exception>
        private void InitCertificate(IntPtr handle, bool duplicate, CertificateStore store)
        {
            if (handle == IntPtr.Zero)
                throw new ArgumentException("Invalid certificate handle!");
            if (duplicate)
                m_Handle = SspiProvider.CertDuplicateCertificateContext(handle);
            else
                m_Handle = handle;
            m_Context = (CertificateContext)Marshal.PtrToStructure(handle, typeof(CertificateContext));

            var certInfo = (OG_CertificateInfo)Marshal.PtrToStructure(m_Context.pCertInfo, typeof(OG_CertificateInfo));
            m_CertInfo = new CertificateInfo()
            {
                dwVersion = certInfo.dwVersion.ToInt32(),
                SerialNumbercbData = certInfo.SerialNumbercbData.ToInt32(),
                SerialNumberpbData = certInfo.SerialNumberpbData,
                SignatureAlgorithmpszObjId = certInfo.SignatureAlgorithmpszObjId,
                SignatureAlgorithmParameterscbData = certInfo.SignatureAlgorithmParameterscbData.ToInt32(),
                SignatureAlgorithmParameterspbData = certInfo.SignatureAlgorithmParameterspbData,
                IssuercbData = certInfo.IssuercbData.ToInt32(),
                IssuerpbData = certInfo.IssuerpbData,
                NotBefore = certInfo.NotBefore,
                NotAfter = certInfo.NotAfter,
                SubjectcbData = certInfo.SubjectcbData.ToInt32(),
                SubjectpbData = certInfo.SubjectpbData,
                SubjectPublicKeyInfoAlgorithmpszObjId = certInfo.SubjectPublicKeyInfoAlgorithmpszObjId,
                SubjectPublicKeyInfoAlgorithmParameterscbData = certInfo.SubjectPublicKeyInfoAlgorithmParameterscbData.ToInt32(),
                SubjectPublicKeyInfoAlgorithmParameterspbData = certInfo.SubjectPublicKeyInfoAlgorithmParameterspbData,
                SubjectPublicKeyInfoPublicKeycbData = certInfo.SubjectPublicKeyInfoPublicKeycbData.ToInt32(),
                SubjectPublicKeyInfoPublicKeypbData = certInfo.SubjectPublicKeyInfoPublicKeypbData,
                SubjectPublicKeyInfoPublicKeycUnusedBits = certInfo.SubjectPublicKeyInfoPublicKeycUnusedBits.ToInt32(),
                IssuerUniqueIdcbData = certInfo.IssuerUniqueIdcbData.ToInt32(),
                IssuerUniqueIdpbData = certInfo.IssuerUniqueIdpbData,
                IssuerUniqueIdcUnusedBits = certInfo.IssuerUniqueIdcUnusedBits.ToInt32(),
                SubjectUniqueIdcbData = certInfo.SubjectUniqueIdcbData.ToInt32(),
                SubjectUniqueIdpbData = certInfo.SubjectUniqueIdpbData,
                SubjectUniqueIdcUnusedBits = certInfo.SubjectUniqueIdcUnusedBits.ToInt32(),
                cExtension = certInfo.cExtension.ToInt32(),
                rgExtension = certInfo.rgExtension
            };
            // end changes OG 2011-10-03
            if (store == null) {
                m_Store = null;
            } else {
                m_Store = store;
            }
        }
		/// <summary>
		/// Removes a certificate store from the collection.
		/// </summary>
		/// <param name="store">An instance of the <see cref="CertificateStore"/> class.</param>
		/// <exception cref="ArgumentNullException"><paramref name="store"/> is a null reference (<b>Nothing</b> in Visual Basic).</exception>
		public void RemoveStore(CertificateStore store) {
			if (store == null)
				throw new ArgumentNullException();
			SspiProvider.CertRemoveStoreFromCollection(this.Handle, store.Handle);
			m_Stores.Remove(store);
		}
        protected byte[] GetDistinguishedNames()
        {
            MemoryStream ms = new MemoryStream();
            byte[] buffer;
            CertificateStore cs = new CertificateStore("ROOT");

            Certificate c = cs.FindCertificate((Certificate)null);
            while(c != null) {
                if( c.IsCurrent )
                {
                    bool include = ( c.GetIntendedKeyUsage() & SecurityConstants.CERT_KEY_CERT_SIGN_KEY_USAGE ) != 0;
                    if( !include )
                    {
                        System.Collections.Specialized.StringCollection usages = c.GetEnhancedKeyUsage();
                        if( usages.Count == 0 || usages.Contains( "1.3.6.1.5.5.7.3.2" ) )
                        {
                            include = true;
                        }
                    }

                    if( include )
                    {
                        buffer = GetDistinguishedName(c);
                        if (ms.Length + buffer.Length + 2 < 65536)
                        {
                            ms.Write(new byte[]{(byte)(buffer.Length / 256), (byte)(buffer.Length % 256)}, 0, 2);
                            ms.Write(buffer, 0, buffer.Length);
                        }
                        else
                        {
                            break;
                        }
                    }
                }
                c = cs.FindCertificate( c );
            }
            return ms.ToArray();
        }
 /// <summary>
 /// see <see cref="Ch.Elca.Iiop.Security.Ssl.IClientSideAuthentication.GetClientCertificate"/>
 /// </summary>
 public override Certificate GetClientCertificate(DistinguishedNameList acceptable) {            
     CertificateStore store = new CertificateStore(m_storeLocation, MY_STORE_NAME);
     Certificate toCheck = store.FindCertificate();
     while(toCheck != null) {                
         if ((toCheck.IsCurrent) && IsClientCertificate(toCheck)) {
             // check, if the root certificate in the chain is known by the server, if yes 
             // -> server will be able to verify the certificate chain
             Certificate[] chain = toCheck.GetCertificateChain().GetCertificates();                    
             if (chain.Length >= 1) {
                 // last certificate in the chain is the root certificate
                 if (IsDistinguishedNameInList(chain[chain.Length - 1].GetDistinguishedName(),
                                               acceptable)) {
                     return toCheck;
                 }
             }
         }
         toCheck = store.FindCertificate(toCheck);
     }
     return null;            
 }    
        protected Certificate LoadCertificateFromStore(StoreLocation storeLocation, string storeName, string certHashString, string certSubject) {

            CertificateStore store = new CertificateStore(storeLocation, storeName);            
            if (certHashString != null) {
                byte[] certHash = GetKeyHashForKeyHashString(certHashString);
                return store.FindCertificateByHash(certHash);
            } else {
                return store.FindCertificateBySubjectString(certSubject);
            }
        }
Example #15
0
 /// <summary>
 /// Find a client certificate in the given store.
 /// </summary>
 /// <param name="store"></param>
 /// <returns></returns>
 public static Certificate FindClientCert(CertificateStore store)
 {
     //return store.FindCertificate(new string[] {OID_PKIX_KP_CLIENT_AUTH});
     return store.FindCertificateByUsage(new string[] {OID_PKIX_KP_CLIENT_AUTH});
 }
Example #16
0
 /// <summary>
 /// Asks the user to specify a server certificate, stored in a certificate store.
 /// </summary>
 /// <returns>A server certificate.</returns>
 private Certificate GetStoreCert()
 {
     try {
         Console.WriteLine("Enter the name of the store (for instance \"MY\", without the quotes):");
         // open the certificate store specified by the user
         CertificateStore cs = new CertificateStore(Console.ReadLine());
         // find a certificate that is suited for server authentication
         Certificate ret = cs.FindCertificateByUsage(new string[] {"1.3.6.1.5.5.7.3.1"});
         if (ret == null)
             Console.WriteLine("The certificate file does not contain a server authentication certificate.");
         return ret;
     } catch {
         Console.WriteLine("An error occurs while opening the specified store.");
         return null;
     }
 }
Example #17
0
		/// <summary>
		/// Initializes a new <see cref="CertificateChain"/> instance from a <see cref="Certificate"/>.
		/// </summary>
		/// <param name="cert">The certificate for which a chain is being built.</param>
		/// <param name="additional">Any additional store to be searched for supporting certificates and CTLs.</param>
		/// <remarks><paramref name="cert"/> will always be the end certificate.</remarks>
		/// <exception cref="ArgumentNullException"><paramref name="cert"/> is a null reference (<b>Nothing</b> in Visual Basic).</exception>
		/// <exception cref="CertificateException">An error occurs while building the certificate chain.</exception>
		public CertificateChain(Certificate cert, CertificateStore additional) : this(cert, additional, CertificateChainOptions.Default) {}
Example #18
0
		protected byte[] GetDistinguishedNames() {
			MemoryStream ms = new MemoryStream();
			byte[] buffer;
			CertificateStore cs = new CertificateStore("ROOT");
			Certificate c = cs.FindCertificate((Certificate)null);
			while(c != null) {
				if ((c.GetIntendedKeyUsage() & SecurityConstants.CERT_KEY_CERT_SIGN_KEY_USAGE) != 0 && c.IsCurrent) {
					buffer = GetDistinguishedName(c);
					if (ms.Length + buffer.Length + 2 < 65536) {
						ms.Write(new byte[]{(byte)(buffer.Length / 256), (byte)(buffer.Length % 256)}, 0, 2);
						ms.Write(buffer, 0, buffer.Length);
					}
				}
				c = cs.FindCertificate(c);
			}
			return ms.ToArray();
		}
Example #19
0
 /// <summary>
 /// Initializes this <see cref="Certificate"/> instance from a handle.
 /// </summary>
 /// <param name="handle">The handle from which to initialize the state of the new instance.</param>
 /// <param name="store">The <see cref="CertificateStore"/> that contains the certificate.</param>
 internal Certificate(IntPtr handle, CertificateStore store)
 {
     InitCertificate(handle, false, store);
 }
Example #20
0
		/// <summary>
		/// Creates a new certificate store from a PFX/P12 encoded file.
		/// </summary>
		/// <param name="file">The contents of a PFX file.</param>
		/// <param name="password">The password used to encrypt the private key.</param>
		/// <param name="exportable"><b>true</b> if the private keys associated with the certificates should be marked as exportable, <b>false</b> otherwise.</param>
		/// <param name="location">One of the <see cref="KeysetLocation"/> values.</param>
		/// <returns>A <see cref="CertificateStore"/> instance.</returns>
		/// <exception cref="ArgumentNullException"><paramref name="file"/> or <paramref name="password"/> is a null reference (<b>Nothing</b> in Visual Basic).</exception>
		/// <exception cref="ArgumentException"><paramref name="password"/> is invalid.</exception>
		/// <exception cref="CertificateException">An error occurs while loading the PFX file.</exception>
		// Thanks go out to Chris Hudel for the implementation of this method.
		public static CertificateStore CreateFromPfxFile(byte[] file, string password, bool exportable, KeysetLocation location) {
			if (password == null || file == null)
				throw new ArgumentNullException("The arguments cannot be null references.");
			CertificateStore cs;
			DataBlob pPFX = new DataBlob();
			// Crypt_data_blob contains two elements,
			// cbData = the size of the blob
			// pbData = a byte array of [cbData] size containing contents of the .p12 file
			pPFX.cbData = file.Length;
			// We need to marshal the byte array Bytes into a pointer so that it can be placed
			// in the structure (class) for the WinAPI call
			IntPtr buffer = Marshal.AllocHGlobal(file.Length);
			Marshal.Copy(file, 0, buffer, file.Length);
			pPFX.pbData = buffer;
			// IF this really is a valid PFX file, then do some work on it 
			try {
				if (SspiProvider.PFXIsPFXBlob(ref pPFX) != 0) {
					if (SspiProvider.PFXVerifyPassword(ref pPFX, password, 0) != 0) {
						int flags = (int)location;
						if (exportable)
							flags |= SecurityConstants.CRYPT_EXPORTABLE;
						IntPtr m_Handle = SspiProvider.PFXImportCertStore(ref pPFX, password, flags);
						if (m_Handle.Equals(IntPtr.Zero)) {
							throw new CertificateException("Unable to import the PFX file! [error code = " + Marshal.GetLastWin32Error() + "]");
						}
						cs = new CertificateStore(m_Handle);
					} else {
						throw new ArgumentException("The specified password is invalid.");
					}
				} else {
					throw new CertificateException("The specified file is not a PFX file.");
				}
			} finally {
				// Free the pointer
				Marshal.FreeHGlobal(buffer);
			}
			return cs;
		}
Example #21
0
 /// <summary>
 /// Initializes this <see cref="Certificate"/> instance from a handle.
 /// </summary>
 /// <param name="handle">The handle from which to initialize the state of the new instance.</param>
 /// <param name="duplicate"><b>true</b> if the handle should be duplicated, <b>false</b> otherwise.</param>
 /// <param name="store">The store that owns the certificate.</param>
 /// <exception cref="ArgumentException"><paramref name="handle"/> is invalid.</exception>
 private void InitCertificate(IntPtr handle, bool duplicate, CertificateStore store)
 {
     if (handle == IntPtr.Zero)
         throw new ArgumentException("Invalid certificate handle!");
     if (duplicate)
         m_Handle = SspiProvider.CertDuplicateCertificateContext(handle);
     else
         m_Handle = handle;
     m_Context = (CertificateContext)Marshal.PtrToStructure(handle, typeof(CertificateContext));
     m_CertInfo = (CertificateInfo)Marshal.PtrToStructure(m_Context.pCertInfo, typeof(CertificateInfo));
     if (store == null) {
         m_Store = null;
     } else {
         m_Store = store;
     }
 }
 private int TestMethods()
 {
     Certificate c = null;
     CertificateStore cs = null;
     try {
         c = CertificateStore.CreateFromCerFile(@"certs\server.base64.cer").FindCertificateByUsage(new string[] {"1.3.6.1.5.5.7.3.1"});
         cs = new CertificateStore();
     } catch {
         AddError("CS-TM-0");
         return 1;
     }
     // AddCertificate + EnumCertificates
     try {
         cs.AddCertificate(null);
         AddError("CS-TM-1");
     } catch (ArgumentNullException) {
     } catch {
         AddError("CS-TM-2");
     }
     try {
         cs.AddCertificate(c);
         if (cs.EnumCertificates().Length != 1)
             AddError("CS-TM-3");
         else
             if (!cs.EnumCertificates()[0].Equals(c))
                 AddError("CS-TM-4");
     } catch {
         AddError("CS-TM-5");
     }
     // DeleteCertificate + EnumCertificates
     try {
         cs.DeleteCertificate(null);
         AddError("CS-TM-6");
     } catch (ArgumentNullException) {
     } catch {
         AddError("CS-TM-7");
     }
     try {
         cs.DeleteCertificate(c);
         if (cs.EnumCertificates().Length != 0)
             AddError("CS-TM-8");
     } catch {
         AddError("CS-TM-9");
     }
     // CreateFromPfxFile
     try {
         cs.AddCertificate(c);
         CertificateStore cs2 = CertificateStore.CreateFromPfxFile(cs.ToPfxBuffer("test", true), "test");
         if (cs2.EnumCertificates().Length != 1)
             AddError("CS-TM-10");
         if (!c.Equals(cs2.EnumCertificates()[0]))
             AddError("CS-TM-11");
     } catch {
         AddError("CS-TM-12");
     }
     // FindCertificate and the CreateFrom*File methods are
     // already tested in other blackbox classes
     return 12;
 }