getCertUsages() {
return list.iterator();
}
@Override
public String toString() {
return name;
}
// certUsage, these must be kept in sync with nss/lib/certdb/certt.h
public static final CertUsage SSLClient = new CertUsage(0, "SSLClient");
public static final CertUsage SSLServer = new CertUsage(1, "SSLServer");
public static final CertUsage SSLServerWithStepUp = new CertUsage(2, "SSLServerWithStepUp");
public static final CertUsage SSLCA = new CertUsage(3, "SSLCA");
public static final CertUsage EmailSigner = new CertUsage(4, "EmailSigner");
public static final CertUsage EmailRecipient = new CertUsage(5, "EmailRecipient");
public static final CertUsage ObjectSigner = new CertUsage(6, "ObjectSigner");
public static final CertUsage UserCertImport = new CertUsage(7, "UserCertImport");
public static final CertUsage VerifyCA = new CertUsage(8, "VerifyCA");
public static final CertUsage ProtectedObjectSigner = new CertUsage(9, "ProtectedObjectSigner");
public static final CertUsage StatusResponder = new CertUsage(10, "StatusResponder");
public static final CertUsage AnyCA = new CertUsage(11, "AnyCA");
}
////////////////////////////////////////////////////
// Module and Token Management
////////////////////////////////////////////////////
/**
* Retrieves the internal cryptographic services token. This is the
* token built into NSS that performs bulk
* cryptographic operations.
* In FIPS mode, the internal cryptographic services token is the
* same as the internal key storage token.
*
* @return The internal cryptographic services token.
*/
@Override
public synchronized CryptoToken getInternalCryptoToken() {
return internalCryptoToken;
}
/**
* Retrieves the internal key storage token. This is the token
* provided by NSS to store private keys.
* The keys stored in this token are stored in an encrypted key database.
*
In FIPS mode, the internal key storage token is the same as
* the internal cryptographic services token.
*
* @return The internal key storage token.
*/
public synchronized CryptoToken getInternalKeyStorageToken() {
return internalKeyStorageToken;
}
/**
* Looks up the CryptoToken with the given name. Searches all
* loaded cryptographic modules for the token.
*
* @param name The name of the token.
* @return The token.
* @exception org.mozilla.jss.NoSuchTokenException If no token
* is found with the given name.
*/
public synchronized CryptoToken getTokenByName(String name)
throws NoSuchTokenException
{
Enumeration tokens = getAllTokens();
CryptoToken token;
while(tokens.hasMoreElements()) {
token = tokens.nextElement();
try {
if( name.equals(token.getName()) ) {
return token;
}
} catch( TokenException e ) {
throw new RuntimeException(e);
}
}
throw new NoSuchTokenException("No such token: " + name);
}
/**
* Retrieves all tokens that support the given algorithm.
*
* @param alg Algorithm.
* @return Enumeration of tokens.
*/
public synchronized Enumeration getTokensSupportingAlgorithm(Algorithm alg)
{
Enumeration tokens = getAllTokens();
Vector goodTokens = new Vector<>();
CryptoToken tok;
while(tokens.hasMoreElements()) {
tok = tokens.nextElement();
if( tok.doesAlgorithm(alg) ) {
goodTokens.addElement(tok);
}
}
return goodTokens.elements();
}
/**
* Retrieves all tokens. This is an enumeration of all tokens on all
* modules.
*
* @return All tokens accessible from JSS. Each item of the enumeration
* is a CryptoToken
* @see org.mozilla.jss.crypto.CryptoToken
*/
public synchronized Enumeration getAllTokens() {
Enumeration modules = getModules();
Enumeration tokens;
Vector allTokens = new Vector<>();
while(modules.hasMoreElements()) {
tokens = modules.nextElement().getTokens();
while(tokens.hasMoreElements()) {
allTokens.addElement( tokens.nextElement() );
}
}
return allTokens.elements();
}
/**
* Retrieves all tokens except those built into NSS.
* This excludes the internal token and the internal
* key storage token (which are one and the same in FIPS mode).
*
* @return All tokens accessible from JSS, except for the built-in
* internal tokens.
*/
public synchronized Enumeration getExternalTokens() {
Enumeration modules = getModules();
Enumeration tokens;
PK11Token token;
Vector allTokens = new Vector<>();
while(modules.hasMoreElements()) {
tokens = modules.nextElement().getTokens();
while(tokens.hasMoreElements()) {
token = (PK11Token) tokens.nextElement();
if( ! token.isInternalCryptoToken() &&
! token.isInternalKeyStorageToken() )
{
allTokens.addElement( token );
}
}
}
return allTokens.elements();
}
/**
* Retrieves all installed cryptographic modules.
*
* @return An enumeration of all installed PKCS #11 modules. Each
* item in the enumeration is a PK11Module
.
* @see org.mozilla.jss.pkcs11.PK11Module
*/
public synchronized Enumeration getModules() {
return moduleVector.elements();
}
// Need to reload modules after adding new one
//public native addModule(String name, String libraryName);
/**
* The list of modules. This should be initialized by the constructor
* and updated whenever 1) a new module is added, 2) a module is deleted,
* or 3) FIPS mode is switched.
*/
private Vector moduleVector;
/**
* Re-creates the Vector of modules that is stored by CryptoManager.
* This entails going into native code to enumerate all modules,
* wrap each one in a PK11Module, and storing the PK11Module in the vector.
*/
private synchronized void reloadModules() {
moduleVector = new Vector<>();
putModulesInVector(moduleVector);
// Get the internal tokens
Enumeration tokens = getAllTokens();
internalCryptoToken = null;
internalKeyStorageToken = null;
while(tokens.hasMoreElements()) {
PK11Token token = (PK11Token) tokens.nextElement();
if( token.isInternalCryptoToken() ) {
assert(internalCryptoToken == null);
internalCryptoToken = token;
}
if( token.isInternalKeyStorageToken() ) {
assert(internalKeyStorageToken == null);
internalKeyStorageToken = token;
}
}
assert(internalKeyStorageToken != null);
assert(internalCryptoToken != null);
}
/**
* The internal cryptographic services token.
*/
private CryptoToken internalCryptoToken;
/**
* The internal key storage token.
*/
private CryptoToken internalKeyStorageToken;
/**
* Native code to traverse all PKCS #11 modules, wrap each one in
* a PK11Module, and insert each PK11Module into the given vector.
*/
private native void putModulesInVector(Vector vector);
///////////////////////////////////////////////////////////////////////
// Constructor and Accessors
///////////////////////////////////////////////////////////////////////
/**
* Constructor, for internal use only.
*/
protected CryptoManager() {
TokenSupplierManager.setTokenSupplier(this);
reloadModules();
}
public static boolean isInitialized() {
synchronized (CryptoManager.class) {
return instance != null;
}
}
/**
* Retrieve the single instance of CryptoManager.
* This cannot be called before initialization.
*
* @see #initialize(InitializationValues)
* @exception NotInitializedException If
* initialize(InitializationValues
has not yet been
* called.
* @return CryptoManager instance.
*/
public static CryptoManager getInstance()
throws NotInitializedException
{
synchronized (CryptoManager.class) {
if (instance != null) {
return instance;
}
}
/* Java has lazy-loading Security providers; until a provider
* is requested, it won't be loaded. This means we could've
* initialized the CryptoManager via the JSSLoader but we won't
* know about it until it is explicitly requested.
*
* This breaks tests looking to configure a file-based password
* handler: if the very first call is to getInstance(...) instead
* of a Provider call, we'd fail.
*
* Try to get the Mozilla-JSS provider by name before reporting
* that we're not initialized.
*
* However, in order for the JSSProvider to load, we need to
* release our lock on CryptoManager (and in particular, on
* CryptoManager.instance).
*
* For a more complete discussion see docs/usage/cryptomanager.md
* in the source distribution.
*/
java.security.Provider p = Security.getProvider("Mozilla-JSS");
synchronized (CryptoManager.class) {
// When instance is properly configured, use that.
if (instance != null) {
return instance;
}
// Otherwise, work around this by looking at what JSSProvider
// created. Note that this will work when CryptoManager no
// longer is a singleton and becomes tied to a specific
// JSSProvider instance.
if (p instanceof JSSProvider) {
JSSProvider jssProvider = (JSSProvider) p;
assert jssProvider.getCryptoManager() != null;
instance = jssProvider.getCryptoManager();
return instance;
}
}
throw new NotInitializedException();
}
/**
* The singleton instance, and a static initializer to create it.
*/
private static CryptoManager instance=null;
///////////////////////////////////////////////////////////////////////
// FIPS management
///////////////////////////////////////////////////////////////////////
/**
* Enables or disables FIPS-140-2 compliant mode. If this returns true,
* you must reloadModules(). This should only be called once in a program,
* at the beginning, because it invalidates tokens and modules.
*
* @param fips true to turn FIPS compliant mode on, false to turn it off.
*/
private static native boolean enableFIPS(boolean fips)
throws GeneralSecurityException;
/**
* Determines whether FIPS-140-2 compliance is active.
*
* @return true if the security library is in FIPS-140-2 compliant mode.
*/
public synchronized native boolean FIPSEnabled();
///////////////////////////////////////////////////////////////////////
// Password Callback management
///////////////////////////////////////////////////////////////////////
/**
* This function sets the global password callback. It is
* not thread-safe to change this.
* The callback may be NULL, in which case password callbacks will
* fail gracefully.
*
* @param pwcb Password callback.
*/
public synchronized void setPasswordCallback(PasswordCallback pwcb) {
passwordCallback = pwcb;
setNativePasswordCallback( pwcb );
}
private native void setNativePasswordCallback(PasswordCallback cb);
/**
* Returns the currently registered password callback.
*
* @return Password callback.
*/
public synchronized PasswordCallback getPasswordCallback() {
return passwordCallback;
}
private PasswordCallback passwordCallback;
////////////////////////////////////////////////////
// Initialization
////////////////////////////////////////////////////
/**
* Initialize the security subsystem. Opens the databases, loads all
* PKCS #11 modules, initializes the internal random number generator.
* The initialize
methods that take arguments should be
* called only once, otherwise they will throw
* an exception. It is OK to call them after calling
* initialize()
.
*
* @param configDir The directory containing the security databases.
* @exception org.mozilla.jss.KeyDatabaseException Unable to open
* the key database, or it was currupted.
* @exception org.mozilla.jss.CertDatabaseException Unable
* to open the certificate database, or it was currupted.
* @exception AlreadyInitializedException If the security subsystem is already initialized.
* @exception GeneralSecurityException If other security error occurred.
**/
public static synchronized void initialize( String configDir )
throws KeyDatabaseException,
CertDatabaseException,
AlreadyInitializedException,
GeneralSecurityException
{
initialize( new InitializationValues(configDir) );
}
public static synchronized void initializeWithContext( String configDir )
throws KeyDatabaseException,
CertDatabaseException,
AlreadyInitializedException,
GeneralSecurityException
{
InitializationValues values = new InitializationValues(configDir);
values.initializeContext = true;
initialize( values );
}
public static synchronized void initializeWithContext( InitializationValues values )
throws
KeyDatabaseException,
CertDatabaseException,
AlreadyInitializedException,
GeneralSecurityException
{
values.initializeContext = true;
initialize( values);
}
/**
* Initialize the security subsystem. Opens the databases, loads all
* PKCS #11 modules, initializes the internal random number generator.
* The initialize
methods that take arguments should be
* called only once, otherwise they will throw
* an exception. It is OK to call them after calling
* initialize()
.
*
* @param values The options with which to initialize CryptoManager.
* @exception org.mozilla.jss.KeyDatabaseException Unable to open
* the key database, or it was corrupted.
* @exception org.mozilla.jss.CertDatabaseException Unable
* to open the certificate database, or it was currupted.
* @exception AlreadyInitializedException If security subsystem is already initialized.
* @exception GeneralSecurityException If other security error occurred.
**/
public static synchronized void initialize( InitializationValues values )
throws
KeyDatabaseException,
CertDatabaseException,
AlreadyInitializedException,
GeneralSecurityException
{
if(instance != null) {
throw new AlreadyInitializedException();
}
if (values.ocspResponderURL != null) {
if (values.ocspResponderCertNickname == null) {
throw new GeneralSecurityException(
"Must set ocspResponderCertNickname");
}
}
//Right now, allow only the choice of a full NSS init or a NSS context init, which is useful for libraries,
//where the main app may have already initialized nss itself.
if(values.initializeContext == true) {
initializeAllNativeWithContext(values.configDir,
values.certPrefix,
values.keyPrefix,
values.secmodName,
values.readOnly,
values.getManufacturerID(),
values.getLibraryDescription(),
values.getInternalTokenDescription(),
values.getInternalKeyStorageTokenDescription(),
values.getInternalSlotDescription(),
values.getInternalKeyStorageSlotDescription(),
values.getFIPSSlotDescription(),
values.getFIPSKeyStorageSlotDescription(),
values.ocspCheckingEnabled,
values.ocspResponderURL,
values.ocspResponderCertNickname,
values.initializeJavaOnly,
values.PKIXVerify,
values.noCertDB,
values.noModDB,
values.forceOpen,
values.noRootInit,
values.optimizeSpace,
values.PK11ThreadSafe,
values.PK11Reload,
values.noPK11Finalize,
values.cooperate
);
} else {
initializeAllNative2(values.configDir,
values.certPrefix,
values.keyPrefix,
values.secmodName,
values.readOnly,
values.getManufacturerID(),
values.getLibraryDescription(),
values.getInternalTokenDescription(),
values.getInternalKeyStorageTokenDescription(),
values.getInternalSlotDescription(),
values.getInternalKeyStorageSlotDescription(),
values.getFIPSSlotDescription(),
values.getFIPSKeyStorageSlotDescription(),
values.ocspCheckingEnabled,
values.ocspResponderURL,
values.ocspResponderCertNickname,
values.initializeJavaOnly,
values.PKIXVerify,
values.noCertDB,
values.noModDB,
values.forceOpen,
values.noRootInit,
values.optimizeSpace,
values.PK11ThreadSafe,
values.PK11Reload,
values.noPK11Finalize,
values.cooperate
);
}
instance = new CryptoManager();
instance.setPasswordCallback(values.passwordCallback);
if( values.fipsMode != InitializationValues.FIPSMode.UNCHANGED) {
if( enableFIPS(values.fipsMode ==
InitializationValues.FIPSMode.ENABLED) )
{
instance.reloadModules();
}
}
// Force class load before we install the provider. Otherwise we get
// an infinite loop as the Security manager tries to instantiate the
// digest to verify its own JAR file.
JSSMessageDigestSpi mds = new JSSMessageDigestSpi.SHA1();
logger.debug("Loaded " + mds);
// Force the KeyType class to load before we can install JSS as a
// provider. JSS's signature provider accesses KeyType.
KeyType kt = KeyType.getKeyTypeFromAlgorithm(
SignatureAlgorithm.RSASignatureWithSHA1Digest);
logger.debug("Loaded " + kt);
if( values.installJSSProvider ) {
int insert_position = 1;
if (!values.installJSSProviderFirst) {
insert_position = java.security.Security.getProviders().length + 1;
}
int position = java.security.Security.insertProviderAt(new JSSProvider(true), insert_position);
if (position < 0) {
logger.warn("JSS provider is already installed");
}
// This returns -1 if the provider was already installed, in which
// case it is not installed again. Is this
// an error? I don't think so, although it might be confusing
// if the provider is not in the position they expected.
// However, this will only happen if they are installing the
// provider themselves, so presumably they know what they're
// doing.
}
if( values.removeSunProvider ) {
java.security.Security.removeProvider("SUN");
}
logger.info("JSS CryptoManager: successfully initialized from NSS database at " + values.configDir);
}
private static native void
initializeAllNative2(String configDir,
String certPrefix,
String keyPrefix,
String secmodName,
boolean readOnly,
String manufacturerID,
String libraryDescription,
String internalTokenDescription,
String internalKeyStorageTokenDescription,
String internalSlotDescription,
String internalKeyStorageSlotDescription,
String fipsSlotDescription,
String fipsKeyStorageSlotDescription,
boolean ocspCheckingEnabled,
String ocspResponderURL,
String ocspResponderCertNickname,
boolean initializeJavaOnly,
boolean PKIXVerify,
boolean noCertDB,
boolean noModDB,
boolean forceOpen,
boolean noRootInit,
boolean optimizeSpace,
boolean PK11ThreadSafe,
boolean PK11Reload,
boolean noPK11Finalize,
boolean cooperate)
throws KeyDatabaseException,
CertDatabaseException,
AlreadyInitializedException;
private static native void
initializeAllNativeWithContext(String configDir,
String certPrefix,
String keyPrefix,
String secmodName,
boolean readOnly,
String manufacturerID,
String libraryDescription,
String internalTokenDescription,
String internalKeyStorageTokenDescription,
String internalSlotDescription,
String internalKeyStorageSlotDescription,
String fipsSlotDescription,
String fipsKeyStorageSlotDescription,
boolean ocspCheckingEnabled,
String ocspResponderURL,
String ocspResponderCertNickname,
boolean initializeJavaOnly,
boolean PKIXVerify,
boolean noCertDB,
boolean noModDB,
boolean forceOpen,
boolean noRootInit,
boolean optimizeSpace,
boolean PK11ThreadSafe,
boolean PK11Reload,
boolean noPK11Finalize,
boolean cooperate)
throws KeyDatabaseException,
CertDatabaseException,
AlreadyInitializedException;
/////////////////////////////////////////////////////////////
// Cert Lookup
/////////////////////////////////////////////////////////////
/**
* Retrieves all CA certificates in the trust database. This
* is a fairly expensive operation in that it involves traversing
* the entire certificate database.
* @return An array of all CA certificates stored permanently
* in the trust database.
*/
public native X509Certificate[]
getCACerts();
/**
* Retrieves all certificates in the trust database. This
* is a fairly expensive operation in that it involves traversing
* the entire certificate database.
* @return An array of all certificates stored permanently
* in the trust database.
*/
public native X509Certificate[]
getPermCerts();
/**
* Imports a chain of certificates. The leaf certificate may be a
* a user certificate, that is, a certificate that belongs to the
* current user and whose private key is available for use.
* If the leaf certificate is a user certificate, it is stored
* on the token
* that contains the corresponding private key, and is assigned the
* given nickname.
*
* @param certPackage An encoded certificate or certificate chain.
* Acceptable
* encodings are binary PKCS #7 SignedData objects and
* DER-encoded certificates, which may or may not be wrapped
* in a Base-64 encoding package surrounded by
* "-----BEGIN CERTIFICATE-----
" and
* "-----END CERTIFICATE-----
".
* @param nickname The nickname for the user certificate. It must
* be unique. It is ignored if there is no user certificate.
* @return The leaf certificate from the chain.
* @exception CertificateEncodingException If the package encoding
* was not recognized.
* @exception NicknameConflictException If the leaf certificate
* is a user certificate, and another certificate already has the
* given nickname.
* @exception UserCertConflictException If the leaf certificate
* is a user certificate, but it has already been imported.
* @exception NoSuchItemOnTokenException If the leaf certificate is
* a user certificate, but the matching private key cannot be found.
* @exception TokenException If an error occurs importing a leaf
* certificate into a token.
*/
public X509Certificate
importCertPackage(byte[] certPackage, String nickname )
throws CertificateEncodingException,
NicknameConflictException,
UserCertConflictException,
NoSuchItemOnTokenException,
TokenException
{
return importCertPackageNative(certPackage, nickname, false, false);
}
/**
* Imports a chain of certificates. The leaf of the chain is a CA
* certificate AND a user certificate (this would only be called by
* a CA installing its own certificate).
*
* @param certPackage An encoded certificate or certificate chain.
* Acceptable
* encodings are binary PKCS #7 SignedData objects and
* DER-encoded certificates, which may or may not be wrapped
* in a Base-64 encoding package surrounded by
* "-----BEGIN CERTIFICATE-----
" and
* "-----END CERTIFICATE-----
".
* @param nickname The nickname for the user certificate. It must
* be unique.
* @return The leaf certificate from the chain.
* @exception CertificateEncodingException If the package encoding
* was not recognized.
* @exception NicknameConflictException If the leaf certificate
* another certificate already has the given nickname.
* @exception UserCertConflictException If the leaf certificate
* has already been imported.
* @exception NoSuchItemOnTokenException If the the private key matching
* the leaf certificate cannot be found.
* @exception TokenException If an error occurs importing the leaf
* certificate into a token.
*/
public X509Certificate
importUserCACertPackage(byte[] certPackage, String nickname)
throws CertificateEncodingException,
NicknameConflictException,
UserCertConflictException,
NoSuchItemOnTokenException,
TokenException
{
return importCertPackageNative(certPackage, nickname, false, true);
}
/**
* Imports a chain of certificates, none of which is a user certificate.
*
* @param certPackage An encoded certificate or certificate chain.
* Acceptable
* encodings are binary PKCS #7 SignedData objects and
* DER-encoded certificates, which may or may not be wrapped
* in a Base-64 encoding package surrounded by
* "-----BEGIN CERTIFICATE-----
" and
* "-----END CERTIFICATE-----
".
* @return The leaf certificate from the chain.
* @exception CertificateEncodingException If the package encoding
* was not recognized.
* @exception TokenException If an error occurs importing a leaf
* certificate into a token.
*/
public X509Certificate
importCACertPackage(byte[] certPackage)
throws CertificateEncodingException,
TokenException
{
try {
return importCertPackageNative(certPackage, null, true, false);
} catch(NicknameConflictException e) {
logger.error("importing CA certs caused nickname conflict", e);
throw new RuntimeException("Importing CA certs caused nickname conflict: " + e.getMessage(), e);
} catch(UserCertConflictException e) {
logger.error("importing CA certs caused user cert conflict", e);
throw new RuntimeException("Importing CA certs caused user cert conflict: " + e.getMessage(), e);
} catch(NoSuchItemOnTokenException e) {
logger.error("importing CA certs caused NoSuchItemOnTokenException", e);
throw new RuntimeException("Importing CA certs caused NoSuchItemOnToken"+
"Exception: " + e.getMessage(), e);
}
}
/**
* Imports a single certificate into the permanent certificate
* database.
*
* @param cert the certificate you want to add
* @param nickname the nickname you want to refer to the certificate as
* (must not be null)
* @return Certificate object.
* @throws TokenException If an error occurred in the token.
* @throws InvalidNicknameException If the nickname is invalid.
*/
public InternalCertificate
importCertToPerm(X509Certificate cert, String nickname)
throws TokenException, InvalidNicknameException
{
if (nickname == null) {
throw new InvalidNicknameException("Nickname must be non-null");
}
return importCertToPermNative(cert,nickname);
}
/**
* Imports a single DER-encoded certificate into the permanent or temporary
* certificate database.
*/
public X509Certificate importDERCert(byte[] cert, CertificateUsage usage,
boolean permanent, String nickname) {
return importDERCertNative(cert, usage.getEnumValue(), permanent, nickname);
}
private native X509Certificate importDERCertNative(byte[] cert, int usage, boolean permanent, String nickname);
private native InternalCertificate
importCertToPermNative(X509Certificate cert, String nickname)
throws TokenException;
/**
* @param noUser true if we know that none of the certs are user certs.
* In this case, no attempt will be made to find a matching private
* key for the leaf certificate.
*/
private native X509Certificate
importCertPackageNative(byte[] certPackage, String nickname,
boolean noUser, boolean leafIsCA)
throws CertificateEncodingException,
NicknameConflictException,
UserCertConflictException,
NoSuchItemOnTokenException,
TokenException;
/*============ CRL importing stuff ********************************/
private static int TYPE_KRL = 0;
private static int TYPE_CRL = 1;
/**
* Imports a CRL, and stores it into the cert7.db
* Validate CRL then import it to the dbase. If there is already a CRL with the
* same CA in the dbase, it will be replaced if derCRL is more up to date.
*
* @param crl the DER-encoded CRL.
* @param url the URL where this CRL can be retrieved from (for future updates).
* [ note that CRLs are not retrieved automatically ]. Can be null
* @exception CRLImportException If the package encoding
* was not recognized.
* @exception TokenException If an error occurred in the token.
*/
public void
importCRL(byte[] crl,String url)
throws CRLImportException,
TokenException
{
importCRLNative(crl,url,TYPE_CRL);
}
/**
* Imports a CRL, and stores it into the cert7.db
*
* @param the DER-encoded CRL.
*/
private native
void importCRLNative(byte[] crl, String url, int rl_type)
throws CRLImportException, TokenException;
/*============ Cert Exporting stuff ********************************/
/**
* Exports one or more certificates into a PKCS #7 certificate container.
* This is just a SignedData object whose certificates
* field contains the given certificates but whose content field
* is empty.
*
* @param certs One or more certificates that should be exported into
* the PKCS #7 object. The leaf certificate should be the first
* in the chain. The output of buildCertificateChain
* would be appropriate here.
* @exception CertificateEncodingException If the array is empty,
* or an error occurred encoding the certificates.
* @return A byte array containing a PKCS #7 SignedData object.
* @see #buildCertificateChain
*/
public native byte[]
exportCertsToPKCS7(X509Certificate[] certs)
throws CertificateEncodingException;
/**
* Looks up a certificate given its nickname.
*
* @param nickname The nickname of the certificate to look for.
* @return The certificate matching this nickname, if one is found.
* @exception ObjectNotFoundException If no certificate could be found
* with the given nickname.
* @exception TokenException If an error occurs in the security library.
*/
public org.mozilla.jss.crypto.X509Certificate
findCertByNickname(String nickname)
throws ObjectNotFoundException, TokenException
{
assert(nickname!=null);
return findCertByNicknameNative(nickname);
}
/**
* Returns all certificates with the given nickname.
*
* @param nickname The nickname of the certificate to look for.
* @return The certificates matching this nickname. The array may be empty
* if no matching certs were found.
* @exception TokenException If an error occurs in the security library.
*/
public org.mozilla.jss.crypto.X509Certificate[]
findCertsByNickname(String nickname)
throws TokenException
{
assert(nickname!=null);
return findCertsByNicknameNative(nickname);
}
/**
* Looks up a certificate by issuer and serial number. The internal
* database and all PKCS #11 modules are searched.
*
* @param derIssuer The DER encoding of the certificate issuer name.
* The issuer name has ASN.1 type Name, which is defined in
* X.501.
* @param serialNumber The certificate serial number.
* @return Certificate object.
* @exception ObjectNotFoundException If the certificate is not found
* in the internal certificate database or on any PKCS #11 token.
* @exception TokenException If an error occurs in the security library.
*/
public org.mozilla.jss.crypto.X509Certificate
findCertByIssuerAndSerialNumber(byte[] derIssuer, INTEGER serialNumber)
throws ObjectNotFoundException, TokenException
{
try {
ANY sn = (ANY) ASN1Util.decode(ANY.getTemplate(),
ASN1Util.encode(serialNumber) );
return findCertByIssuerAndSerialNumberNative(derIssuer,
sn.getContents() );
} catch( InvalidBERException e ) {
throw new RuntimeException("Invalid BER encoding of INTEGER: " + e.getMessage(), e);
}
}
/**
* @param serialNumber The contents octets of a DER-encoding of the
* certificate serial number.
*/
private native org.mozilla.jss.crypto.X509Certificate
findCertByIssuerAndSerialNumberNative(byte[] derIssuer, byte[] serialNumber)
throws ObjectNotFoundException, TokenException;
protected native org.mozilla.jss.crypto.X509Certificate
findCertByNicknameNative(String nickname)
throws ObjectNotFoundException, TokenException;
protected native org.mozilla.jss.crypto.X509Certificate[]
findCertsByNicknameNative(String nickname)
throws TokenException;
/////////////////////////////////////////////////////////////
// build cert chains
/////////////////////////////////////////////////////////////
/**
* Given a certificate, constructs its certificate chain. It may
* or may not chain up to a trusted root.
* @param leaf The certificate that is the starting point of the chain.
* @return An array of certificates, starting at the leaf and ending
* with the highest certificate on the chain that was found.
* @throws CertificateException If the certificate is not recognized
* by the underlying provider.
* @throws TokenException If an error occurred in the token.
*/
public org.mozilla.jss.crypto.X509Certificate[]
buildCertificateChain(org.mozilla.jss.crypto.X509Certificate leaf)
throws java.security.cert.CertificateException, TokenException
{
if( ! (leaf instanceof PK11Cert) ) {
throw new CertificateException(
"Certificate is not a PKCS #11 certificate");
}
return buildCertificateChainNative((PK11Cert)leaf);
}
native org.mozilla.jss.crypto.X509Certificate[]
buildCertificateChainNative(PK11Cert leaf)
throws CertificateException, TokenException;
/////////////////////////////////////////////////////////////
// lookup private keys
/////////////////////////////////////////////////////////////
/**
* Looks up the PrivateKey matching the given certificate.
*
* @param cert Certificate.
* @return Private key.
* @exception ObjectNotFoundException If no private key can be
* found matching the given certificate.
* @exception TokenException If an error occurs in the security library.
*/
public org.mozilla.jss.crypto.PrivateKey
findPrivKeyByCert(org.mozilla.jss.crypto.X509Certificate cert)
throws ObjectNotFoundException, TokenException
{
assert(cert!=null);
if(! (cert instanceof org.mozilla.jss.pkcs11.PK11Cert)) {
throw new ObjectNotFoundException("Non-pkcs11 cert passed to PK11Finder");
}
return findPrivKeyByCertNative(cert);
}
protected native org.mozilla.jss.crypto.PrivateKey
findPrivKeyByCertNative(org.mozilla.jss.crypto.X509Certificate cert)
throws ObjectNotFoundException, TokenException;
/////////////////////////////////////////////////////////////
// Provide Pseudo-Random Number Generation
/////////////////////////////////////////////////////////////
/**
* Retrieves a FIPS-140-2 validated random number generator.
*
* @return A JSS SecureRandom implemented with FIPS-validated NSS.
*/
public org.mozilla.jss.crypto.JSSSecureRandom
createPseudoRandomNumberGenerator()
{
return new PK11SecureRandom();
}
/**
* Retrieves a FIPS-140-2 validated random number generator.
*
* @return A JSS SecureRandom implemented with FIPS-validated NSS.
*/
@Override
public org.mozilla.jss.crypto.JSSSecureRandom
getSecureRNG() {
return new PK11SecureRandom();
}
/********************************************************************/
/* The VERSION Strings should be updated everytime a new release */
/* of JSS is generated. Note that this is done by changing */
/* cmake/JSSConfig.cmake. */
/********************************************************************/
public static native int getJSSMajorVersion();
public static native int getJSSMinorVersion();
public static native int getJSSPatchVersion();
public static final String getJSSVersion() {
return String.format("%d.%d.%d", getJSSMajorVersion(), getJSSMinorVersion(), getJSSPatchVersion());
}
public static native boolean getJSSDebug();
public static final boolean JSS_DEBUG = getJSSDebug();
private ThreadLocal threadToken = new ThreadLocal<>();
/**
* Sets the default token for the current thread. This token will
* be used when JSS is called through the JCA interface, which has
* no means of specifying which token to use.
*
* If no token is set, the InternalKeyStorageToken will be used. Setting
* this thread's token to null
will also cause the
* InternalKeyStorageToken to be used.
*
* @param token The token to use for crypto operations. Specifying
* null
will cause the InternalKeyStorageToken to be used.
*/
@Override
public void setThreadToken(CryptoToken token) {
if( token != null ) {
threadToken.set(token);
} else {
threadToken.remove();
}
}
/**
* Returns the default token for the current thread. This token will
* be used when JSS is called through the JCA interface, which has
* no means of specifying which token to use.
*
*
If no token is set, the InternalKeyStorageToken will be used. Setting
* this thread's token to null
will also cause the
* InternalKeyStorageToken to be used.
*
* @return The default token for this thread. If it has not been specified,
* it will be the InternalKeyStorageToken.
*/
@Override
public CryptoToken getThreadToken() {
CryptoToken tok = threadToken.get();
if( tok == null ) {
tok = getInternalKeyStorageToken();
}
return tok;
}
/////////////////////////////////////////////////////////////
// isCertValid
/////////////////////////////////////////////////////////////
/**
* Verify a certificate that exists in the given cert database,
* check if is valid and that we trust the issuer. Verify time
* against Now.
* @param nickname The nickname of the certificate to verify.
* @param checkSig verify the signature of the certificate
* @return currCertificateUsage which contains current usage bit map as defined in CertificateUsage
*
* @exception InvalidNicknameException If the nickname is null
* @exception ObjectNotFoundException If no certificate could be found
* with the given nickname.
*/
public int isCertValid(String nickname, boolean checkSig)
throws ObjectNotFoundException, InvalidNicknameException
{
if (nickname==null) {
throw new InvalidNicknameException("Nickname must be non-null");
}
int currCertificateUsage = 0x0000; // initialize it to 0
currCertificateUsage = verifyCertificateNowCUNative(nickname,
checkSig);
return currCertificateUsage;
}
private native int verifyCertificateNowCUNative(String nickname,
boolean checkSig) throws ObjectNotFoundException;
/////////////////////////////////////////////////////////////
// isCertValid
/////////////////////////////////////////////////////////////
/**
* Verify a certificate that exists in the given cert database,
* check if is valid and that we trust the issuer. Verify time
* against Now.
* @param nickname The nickname of the certificate to verify.
* @param checkSig verify the signature of the certificate
* @param certificateUsage see certificateUsage defined to verify Certificate; to retrieve current certificate usage, call the isCertValid() above
* @return true for success; false otherwise
*
* @exception InvalidNicknameException If the nickname is null
* @exception ObjectNotFoundException If no certificate could be found
* with the given nickname.
* @deprecated Use verifyCertificate() instead
*/
@Deprecated
public boolean isCertValid(String nickname, boolean checkSig,
CertificateUsage certificateUsage)
throws ObjectNotFoundException, InvalidNicknameException
{
if (nickname==null) {
throw new InvalidNicknameException("Nickname must be non-null");
}
// 0 certificate usage will get current usage
// should call isCertValid() call above that returns certificate usage
if (certificateUsage == null || certificateUsage == CertificateUsage.CheckAllUsages) {
int currCertificateUsage = verifyCertificateNowCUNative(nickname, checkSig);
return currCertificateUsage != CertificateUsage.basicCertificateUsages;
}
return verifyCertificateNowNative(nickname, checkSig,
certificateUsage.getUsage());
}
/**
* Verify a certificate that exists in the given cert database,
* check if it's valid and that we trust the issuer. Verify time
* against now.
* @param nickname nickname of the certificate to verify.
* @param checkSig verify the signature of the certificate
* @param certificateUsage see certificate usage defined to verify certificate
*
* @exception InvalidNicknameException If the nickname is null.
* @exception ObjectNotFoundException If no certificate could be found
* with the given nickname.
* @exception CertificateException If certificate is invalid.
*/
public void verifyCertificate(String nickname,
boolean checkSig,
CertificateUsage certificateUsage)
throws ObjectNotFoundException, InvalidNicknameException, CertificateException {
int usage = certificateUsage == null ? 0 : certificateUsage.getUsage();
verifyCertificateNowNative2(nickname, checkSig, usage);
}
/**
* Verify an X509Certificate by checking if it's valid and that we trust
* the issuer. Verify time against now.
* @param cert the certificate to verify
* @param checkSig verify the signature of the certificate
* @param certificateUsage see certificate usage defined to verify certificate
*
* @exception InvalidNicknameException If the nickname is null.
* @exception ObjectNotFoundException If no certificate could be found
* with the given nickname.
* @exception CertificateException If certificate is invalid.
*/
public void verifyCertificate(X509Certificate cert, boolean checkSig,
CertificateUsage certificateUsage) throws ObjectNotFoundException,
InvalidNicknameException, CertificateException {
int usage = certificateUsage == null ? 0 : certificateUsage.getUsage();
verifyCertificateNowNative3(cert, checkSig, usage);
}
private native boolean verifyCertificateNowNative(String nickname,
boolean checkSig, int certificateUsage) throws ObjectNotFoundException;
private native void verifyCertificateNowNative2(
String nickname,
boolean checkSig,
int certificateUsage)
throws ObjectNotFoundException, InvalidNicknameException, CertificateException;
private native void verifyCertificateNowNative3(
X509Certificate cert,
boolean checkSig,
int certificateUsage)
throws ObjectNotFoundException, InvalidNicknameException, CertificateException;
/**
* note: this method calls obsolete function in NSS
*
* Verify a certificate that exists in the given cert database,
* check if is valid and that we trust the issuer. Verify time
* against Now.
* @param nickname The nickname of the certificate to verify.
* @param checkSig verify the signature of the certificate
* @param certUsage see exposed certUsage defines to verify Certificate
* @return true for success; false otherwise
*
* @exception InvalidNicknameException If the nickname is null
* @exception ObjectNotFoundException If no certificate could be found
* with the given nickname.
*/
public boolean isCertValid(String nickname, boolean checkSig,
CertUsage certUsage)
throws ObjectNotFoundException, InvalidNicknameException
{
if (nickname==null) {
throw new InvalidNicknameException("Nickname must be non-null");
}
return verifyCertNowNative(nickname, checkSig, certUsage.getUsage());
}
/*
* Obsolete in NSS
*/
private native boolean verifyCertNowNative(String nickname,
boolean checkSig, int cUsage) throws ObjectNotFoundException;
/////////////////////////////////////////////////////////////
// isCertValid
/////////////////////////////////////////////////////////////
/**
* Verify a certificate in memory. Check if
* valid and that we trust the issuer. Verify time
* against Now.
* @param certPackage certificate in memory
* @param checkSig verify the signature of the certificate
* @param certUsage see exposed certUsage defines to verify Certificate
* @return true for success; false otherwise
*
* @exception TokenException unable to insert temporary certificate
* into database.
* @exception CertificateEncodingException If the package encoding
* was not recognized.
*/
public boolean isCertValid(byte[] certPackage, boolean checkSig,
CertUsage certUsage)
throws TokenException, CertificateEncodingException
{
return verifyCertTempNative(certPackage , checkSig,
certUsage.getUsage());
}
private native boolean verifyCertTempNative(byte[] certPackage,
boolean checkSig, int cUsage)
throws TokenException, CertificateEncodingException;
///////////////////////////////////////////////////////////////////////
// OCSP management
///////////////////////////////////////////////////////////////////////
/* OCSP Policy related */
public enum OCSPPolicy {
NONE,
NORMAL,
LEAF_AND_CHAIN;
}
private static OCSPPolicy ocspPolicy = OCSPPolicy.NONE;
/**
* Gets the current ocsp Policy.
* Currently we only support 2 modes OCSP_LEAF_AND_CHAIN_POLICY.
* And OCSP_NORMAL_POLICY, which is current processing , by default.
* If we have AIA based OCSP enabled we will check all certs in the chain.
* using PKIX cert verfication calls in the various cert auth callbacks we
* have.
* @return - The current ocsp policy in effect.
*/
public static synchronized int getOCSPPolicy() {
return ocspPolicy.ordinal();
}
/**
* Gets the current OCSP Policy.
*
* @see getOCSPPolicy()
*
* @return - The current OCSP policy in effect.
*/
public static synchronized OCSPPolicy getOCSPPolicyEnum() {
return ocspPolicy;
}
/**
* Sets the current ocsp Policy.
* Currently we only support one mode OCSP_LEAF_AND_CHAIN_POLICY.
* If we have AIA based OCSP enabled we will check all certs in the chain.
* using PKIX cert verfication calls in the various cert auth callbacks we
* have.
* @param policy - Either cert and chain or normal default processing.
*
*/
public static synchronized void setOCSPPolicy(OCSPPolicy policy) {
ocspPolicy = policy;
}
/**
* Enables OCSP, note when you Initialize JSS for the first time, for
* backwards compatibility, the initialize will enable OCSP if you
* previously set values.ocspCheckingEnabled and
* values.ocspResponderURL/values.ocspResponderCertNickname
* configureOCSP will allow changing of the the OCSPResponder at runtime.
* @param ocspCheckingEnabled true or false to enable/disable OCSP
* @param ocspResponderURL - url of the OCSP responder
* @param ocspResponderCertNickname - the nickname of the OCSP
* signer certificate or the CA certificate found in the cert DB
* @throws GeneralSecurityException If a security error has occurred.
*/
public void configureOCSP(
boolean ocspCheckingEnabled,
String ocspResponderURL,
String ocspResponderCertNickname )
throws GeneralSecurityException
{
/* set the ocsp policy */
if(ocspCheckingEnabled &&
ocspResponderURL == null &&
ocspResponderCertNickname == null) {
setOCSPPolicy(OCSPPolicy.LEAF_AND_CHAIN);
} else {
setOCSPPolicy(OCSPPolicy.NORMAL);
}
configureOCSPNative(ocspCheckingEnabled,
ocspResponderURL,
ocspResponderCertNickname );
}
private native void configureOCSPNative( boolean ocspCheckingEnabled,
String ocspResponderURL,
String ocspResponderCertNickname )
throws GeneralSecurityException;
/**
* change OCSP cache settings
* @param ocsp_cache_size max cache entries
* @param ocsp_min_cache_entry_duration minimum seconds to next fetch attempt
* @param ocsp_max_cache_entry_duration maximum seconds to next fetch attempt
* @throws GeneralSecurityException If a security error has occurred.
*/
public void OCSPCacheSettings(
int ocsp_cache_size,
int ocsp_min_cache_entry_duration,
int ocsp_max_cache_entry_duration)
throws GeneralSecurityException
{
OCSPCacheSettingsNative(ocsp_cache_size,
ocsp_min_cache_entry_duration,
ocsp_max_cache_entry_duration);
}
private native void OCSPCacheSettingsNative(
int ocsp_cache_size,
int ocsp_min_cache_entry_duration,
int ocsp_max_cache_entry_duration)
throws GeneralSecurityException;
/**
* set OCSP timeout value
* @param ocsp_timeout OCSP timeout in seconds
* @throws GeneralSecurityException If a security error has occurred.
*/
public void setOCSPTimeout(
int ocsp_timeout )
throws GeneralSecurityException
{
setOCSPTimeoutNative( ocsp_timeout);
}
private native void setOCSPTimeoutNative(
int ocsp_timeout )
throws GeneralSecurityException;
/**
* Shutdowns this CryptoManager instance and the associated NSS
* initialization.
*/
public synchronized void shutdown() throws Exception {
try {
NativeProxy.purgeAllInRegistry();
} finally {
shutdownNative();
CryptoManager.instance = null;
}
}
public native void shutdownNative();
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/DatabaseCloser.java 0000664 0000000 0000000 00000003024 14565430767 0024462 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss;
/**
* A class for closing databases. Since closing the databases is
* very dangerous and breaks the JSS model, it may only be done from
* special applications. This class should be subclasses by
* authorized subclasses. It cannot be instantiated itself.
*/
public abstract class DatabaseCloser {
private static final String authorizedClosers[] =
{ "org.mozilla.certsetup.apps.CertSetup$DatabaseCloser",
"org.mozilla.jss.CloseDBs" };
/**
* Creates a new DatabaseCloser. This should only be called
* from an authorized subclass. This class cannot itself be
* instantiated.
*
* @throws Exception If the instantiation is not a valid subclass.
*/
public DatabaseCloser() throws Exception {
Class> clazz = this.getClass();
String name = clazz.getName();
boolean approved = false;
for(int i=0; i < authorizedClosers.length; i++) {
if( name.equals( authorizedClosers[i] ) ) {
approved = true;
break;
}
}
if(!approved) {
throw new Exception();
}
}
/**
* Closes the certificate and key databases. This is extremely
* dangerous.
*/
protected native void closeDatabases();
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/InitializationValues.java 0000664 0000000 0000000 00000047071 14565430767 0025767 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss;
import org.mozilla.jss.util.ConsolePasswordCallback;
import org.mozilla.jss.util.PasswordCallback;
/**
* The various options that can be used to initialize CryptoManager.
*/
public final class InitializationValues {
protected InitializationValues() {
throw new RuntimeException("Default InitializationValues constructor");
}
/////////////////////////////////////////////////////////////
// Constants
/////////////////////////////////////////////////////////////
/**
* Token names must be this length exactly.
*/
public final int TOKEN_LENGTH = 33;
/**
* Slot names must be this length exactly.
*/
public final int SLOT_LENGTH = 65;
/**
* ManufacturerID must be this length exactly.
*/
public final int MANUFACTURER_LENGTH = 33;
/**
* Library description must be this length exactly.
*/
public final int LIBRARY_LENGTH = 33;
/**
* This class enumerates the possible modes for FIPS compliance.
*/
public static final class FIPSMode {
private FIPSMode() {}
/**
* Enable FIPS mode.
*/
public static final InitializationValues.FIPSMode ENABLED = new FIPSMode();
/**
* Disable FIPS mode.
*/
public static final InitializationValues.FIPSMode DISABLED = new FIPSMode();
/**
* Leave FIPS mode unchanged. All servers except Admin
* Server should use this, because only Admin Server should
* be altering FIPS mode.
*/
public static final InitializationValues.FIPSMode UNCHANGED = new FIPSMode();
}
/**
* Default constructor taking only the path to the NSS DB directory.
*/
public InitializationValues(String configDir) {
this.configDir = configDir;
}
/**
* Optional constructor taking the path to the NSS DB directory,
* the prefix of the cert database, the prefix of the key database,
* and the name of the secmod/pkcs11 database.
*/
public InitializationValues(String configDir, String certPrefix,
String keyPrefix, String secmodName)
{
this.configDir = configDir;
this.certPrefix = certPrefix;
this.keyPrefix = keyPrefix;
this.secmodName = secmodName;
}
public String configDir = null;
public String certPrefix = null;
public String keyPrefix = null;
public String secmodName = null;
/**
* The password callback to be used by JSS whenever a password
* is needed. May be NULL, in which the library will immediately fail
* to get a password if it tries to login automatically while
* performing
* a cryptographic operation. It will still work if the token
* has been manually logged in with CryptoToken.login
.
*
The default is a ConsolePasswordCallback
.
*/
public PasswordCallback passwordCallback =
new ConsolePasswordCallback();
/**
* The FIPS mode of the security library. Servers should
* use FIPSMode.UNCHANGED
, since only
* Admin Server is supposed to alter this value.
*
The default is FIPSMode.UNCHANGED
.
*/
public InitializationValues.FIPSMode fipsMode = FIPSMode.UNCHANGED;
/**
* To open the databases in read-only mode, set this flag to
* true
. The default is false
, meaning
* the databases are opened in read-write mode.
*/
public boolean readOnly = false;
public boolean initializeContext = false;
/**
* Returns boolean value of initializeContext.
*
The default is "false "
.
*
* @return initializeContext.
*/
public boolean getInitializeContext() { return initializeContext; }
/**
* Sets boolean value of initializeContext.
* @param value of initializeContext.
*/
public void setInitializeContext(boolean value) {
this.initializeContext = value;
}
////////////////////////////////////////////////////////////////////
// Manufacturer ID
////////////////////////////////////////////////////////////////////
/**
* Returns the Manufacturer ID of the internal PKCS #11 module.
*
The default is "mozilla.org "
.
*
* @return Manufacturer ID.
*/
public String getManufacturerID() { return manufacturerID; }
/**
* Sets the Manufacturer ID of the internal PKCS #11 module.
* This value must be exactly MANUFACTURER_LENGTH
* characters long.
*
* @param s Manufacturer ID.
* @exception InvalidLengthException If s.length()
is not
* exactly MANUFACTURER_LENGTH
.
*/
public void setManufacturerID(String s) throws InvalidLengthException {
if (s.length() != MANUFACTURER_LENGTH) {
String msg = "Expected internal manufacturer ID description ";
msg += "of length " + MANUFACTURER_LENGTH + " but was ";
msg += s.length();
throw new InvalidLengthException();
}
manufacturerID = s;
}
private String manufacturerID =
"mozilla.org ";
////////////////////////////////////////////////////////////////////
// Library Description
////////////////////////////////////////////////////////////////////
/**
* Returns the description of the internal PKCS #11 module.
*
The default is "Internal Crypto Services "
.
*
* @return Library description.
*/
public String getLibraryDescription() { return libraryDescription; }
/**
* Sets the description of the internal PKCS #11 module.
* This value must be exactly LIBRARY_LENGTH
* characters long.
*
* @param s Library description.
* @exception InvalidLengthException If s.length()
is
* not exactly LIBRARY_LENGTH
.
*/
public void setLibraryDescription(String s)
throws InvalidLengthException
{
if (s.length() != LIBRARY_LENGTH) {
String msg = "Expected internal library description of length ";
msg += LIBRARY_LENGTH + " but was " + s.length();
throw new InvalidLengthException(msg);
}
libraryDescription = s;
}
private String libraryDescription =
"Internal Crypto Services ";
////////////////////////////////////////////////////////////////////
// Internal Token Description
////////////////////////////////////////////////////////////////////
/**
* Returns the description of the internal PKCS #11 token.
*
The default is "Internal Crypto Services Token "
.
*
* @return Description of internal PKCS #11 token.
*/
public String getInternalTokenDescription() {
return internalTokenDescription;
}
/**
* Sets the description of the internal PKCS #11 token.
* This value must be exactly TOKEN_LENGTH
characters long.
*
* @param s Description of internal PKCS #11 token.
* @exception InvalidLengthException If s.length()
is
* not exactly TOKEN_LENGTH
.
*/
public void setInternalTokenDescription(String s)
throws InvalidLengthException
{
if (s.length() != TOKEN_LENGTH) {
String msg = "Expected internal token description of length ";
msg += TOKEN_LENGTH + " but was " + s.length();
throw new InvalidLengthException(msg);
}
internalTokenDescription = s;
}
private String internalTokenDescription =
"NSS Generic Crypto Services ";
////////////////////////////////////////////////////////////////////
// Internal Key Storage Token Description
////////////////////////////////////////////////////////////////////
/**
* Returns the description of the internal PKCS #11 key storage token.
*
The default is "Internal Key Storage Token "
.
*
* @return Description of internal PKCS #11 key storage token.
*/
public String getInternalKeyStorageTokenDescription() {
return internalKeyStorageTokenDescription;
}
/**
* Sets the description of the internal PKCS #11 key storage token.
* This value must be exactly TOKEN_LENGTH
characters long.
*
* @param s Description of internal PKCS #11 key storage token.
* @exception InvalidLengthException If s.length()
is
* not exactly TOKEN_LENGTH
.
*/
public void setInternalKeyStorageTokenDescription(String s)
throws InvalidLengthException
{
if (s.length() != TOKEN_LENGTH) {
String msg = "Expected internal key storage token description ";
msg += "of length " + TOKEN_LENGTH + " but was " + s.length();
throw new InvalidLengthException(msg);
}
internalKeyStorageTokenDescription = s;
}
private String internalKeyStorageTokenDescription =
"Internal Key Storage Token ";
////////////////////////////////////////////////////////////////////
// Internal Slot Description
////////////////////////////////////////////////////////////////////
/**
* Returns the description of the internal PKCS #11 slot.
*
The default is "NSS Internal Cryptographic Services "
.
*
* @return Description of internal PKCS #11 slot.
*/
public String getInternalSlotDescription() {
return internalSlotDescription;
}
/**
* Sets the description of the internal PKCS #11 slot.
* This value must be exactly SLOT_LENGTH
characters
* long.
*
* @param s Description of internal PKCS #11 slot.
* @exception InvalidLengthException If s.length()
is
* not exactly SLOT_LENGTH
.
*/
public void setInternalSlotDescription(String s)
throws InvalidLengthException
{
if (s.length() != SLOT_LENGTH) {
String msg = "Expected internal slot description of length ";
msg += SLOT_LENGTH + " but was " + s.length();
throw new InvalidLengthException(msg);
}
internalSlotDescription = s;
}
private String internalSlotDescription =
"NSS Internal Cryptographic Services ";
////////////////////////////////////////////////////////////////////
// Internal Key Storage Slot Description
////////////////////////////////////////////////////////////////////
/**
* Returns the description of the internal PKCS #11 key storage slot.
*
The default is "NSS Internal Private Key and Certificate Storage "
.
*
* @return Description of internal PKCS #11 key storage slot.
*/
public String getInternalKeyStorageSlotDescription() {
return internalKeyStorageSlotDescription;
}
/**
* Sets the description of the internal PKCS #11 key storage slot.
* This value must be exactly SLOT_LENGTH
characters
* long.
*
* @param s Description of internal PKCS #11 key storage slot.
* @exception InvalidLengthException If s.length()
is
* not exactly SLOT_LENGTH
.
*/
public void setInternalKeyStorageSlotDescription(String s)
throws InvalidLengthException
{
if (s.length() != SLOT_LENGTH) {
String msg = "Expected internal key storage slot description of ";
msg += "length " + SLOT_LENGTH + " but was " + s.length();
throw new InvalidLengthException(msg);
}
internalKeyStorageSlotDescription = s;
}
private String internalKeyStorageSlotDescription =
"NSS User Private Key and Certificate Services ";
////////////////////////////////////////////////////////////////////
// FIPS Slot Description
////////////////////////////////////////////////////////////////////
/**
* Returns the description of the internal PKCS #11 FIPS slot.
*
The default is
* "NSS FIPS 140-2 User Private Key Services"
.
*
* @return Description of internal PKCS #11 FIPS slot.
*/
public String getFIPSSlotDescription() {
return FIPSSlotDescription;
}
/**
* Sets the description of the internal PKCS #11 FIPS slot.
* This value must be exactly SLOT_LENGTH
characters
* long.
*
* @param s Description of internal PKCS #11 FIPS slot.
* @exception InvalidLengthException If s.length()
is
* not exactly SLOT_LENGTH
.
*/
public void setFIPSSlotDescription(String s)
throws InvalidLengthException
{
if (s.length() != SLOT_LENGTH) {
String msg = "Expected FIPS slot description of length ";
msg += SLOT_LENGTH + " but was " + s.length();
throw new InvalidLengthException(msg);
}
FIPSSlotDescription = s;
}
private String FIPSSlotDescription =
"NSS FIPS 140-2 User Private Key Services ";
////////////////////////////////////////////////////////////////////
// FIPS Key Storage Slot Description
////////////////////////////////////////////////////////////////////
/**
* Returns the description of the internal PKCS #11 FIPS
* Key Storage slot.
*
The default is
* "NSS FIPS 140-2 User Private Key Services"
.
*
* @return Description of internal PKCS #11 FIPS key storage slot.
*/
public String getFIPSKeyStorageSlotDescription() {
return FIPSKeyStorageSlotDescription;
}
/**
* Sets the description of the internal PKCS #11 FIPS Key Storage slot.
* This value must be exactly SLOT_LENGTH
characters
* long.
*
* @param s Description of internal PKCS #11 FIPS key storage slot.
* @exception InvalidLengthException If s.length()
is
* not exactly SLOT_LENGTH
.
*/
public void setFIPSKeyStorageSlotDescription(String s)
throws InvalidLengthException
{
if (s.length() != SLOT_LENGTH) {
String msg = "Expected FIPS key storage slot description of ";
msg += "length " + SLOT_LENGTH + " but was " + s.length();
throw new InvalidLengthException(msg);
}
FIPSKeyStorageSlotDescription = s;
}
private String FIPSKeyStorageSlotDescription =
"NSS FIPS 140-2 User Private Key Services ";
/**
* To have NSS check the OCSP responder for when verifying
* certificates, set this flags to true. It is false by
* default.
*/
public boolean ocspCheckingEnabled = false;
/**
* Specify the location and cert of the responder.
* If OCSP checking is enabled *and* this variable is
* set to some URL, all OCSP checking will be done via
* this URL.
*
* If this variable is null, the OCSP responder URL will
* be obtained from the AIA extension in the certificate
* being queried.
*
* If this is set, you must also set ocspResponderCertNickname
*
*/
public String ocspResponderURL = null;
/**
* The nickname of the cert to trust (expected) to
* sign the OCSP responses.
* Only checked when the OCSPResponder value is set.
*/
public String ocspResponderCertNickname = null;
/**
* Install the JSS crypto provider. Default is true.
*/
public boolean installJSSProvider = true;
/**
* Remove the Sun crypto provider. Default is false.
*/
public boolean removeSunProvider = false;
/**
* Whether or not to initialize the JSS provider first. Default is true.
*/
public boolean installJSSProviderFirst = true;
/**
* If true
, none of the underlying NSS components will
* be initialized. Only the Java portions of JSS will be
* initialized. This should only be used if NSS has been initialized
* elsewhere.
*
*
Specifically, the following components will not be
* configured by CryptoManager.initialize
if this flag is set:
*
* - The NSS databases.
*
- OCSP checking.
*
- The NSS password callback.
*
- The internal PKCS #11 software token's identifier labels:
* slot, token, module, and manufacturer.
*
- The minimum PIN length for the software token.
*
- The frequency with which the user must login to the software
* token.
*
- The cipher strength policy (export/domestic).
*
*
* The default is false
.
*/
public boolean initializeJavaOnly = false;
/**
* Enable PKIX verify rather than the old cert library,
* to verify certificates. Default is false.
*/
public boolean PKIXVerify = false;
/**
* Don't open the cert DB and key DB's, just
* initialize the volatile certdb. Default is false.
*/
public boolean noCertDB = false;
/**
* Don't open the security module DB,
* just initialize the PKCS #11 module.
* Default is false.
*/
public boolean noModDB = false;
/**
* Continue to force initializations even if the
* databases cannot be opened.
* Default is false.
*/
public boolean forceOpen = false;
/**
* Don't try to look for the root certs module
* automatically.
* Default is false.
*/
public boolean noRootInit = false;
/**
* Use smaller tables and caches.
* Default is false.
*/
public boolean optimizeSpace = false;
/**
* only load PKCS#11 modules that are
* thread-safe, ie. that support locking - either OS
* locking or NSS-provided locks . If a PKCS#11
* module isn't thread-safe, don't serialize its
* calls; just don't load it instead. This is necessary
* if another piece of code is using the same PKCS#11
* modules that NSS is accessing without going through
* NSS, for example the Java SunPKCS11 provider.
* Default is false.
*/
public boolean PK11ThreadSafe = false;
/**
* Init PK11Reload to ignore the CKR_CRYPTOKI_ALREADY_INITIALIZED
* error when loading PKCS#11 modules. This is necessary
* if another piece of code is using the same PKCS#11
* modules that NSS is accessing without going through
* NSS, for example Java SunPKCS11 provider.
* Default is false.
*/
public boolean PK11Reload = false;
/**
* never call C_Finalize on any
* PKCS#11 module. This may be necessary in order to
* ensure continuous operation and proper shutdown
* sequence if another piece of code is using the same
* PKCS#11 modules that NSS is accessing without going
* through NSS, for example Java SunPKCS11 provider.
* The following limitation applies when this is set :
* SECMOD_WaitForAnyTokenEvent will not use
* C_WaitForSlotEvent, in order to prevent the need for
* C_Finalize. This call will be emulated instead.
* Default is false.
*/
public boolean noPK11Finalize = false;
/**
* Sets 4 recommended options for applications that
* use both NSS and the Java SunPKCS11 provider.
* Default is false.
*/
public boolean cooperate = false;
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/InvalidLengthException.java 0000664 0000000 0000000 00000001370 14565430767 0026217 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss;
public final class InvalidLengthException extends Exception {
private static final long serialVersionUID = 1L;
public InvalidLengthException() {}
public InvalidLengthException(String mesg) {
super(mesg);
}
public InvalidLengthException(String mesg, Throwable cause) {
super(mesg, cause);
}
public InvalidLengthException(String mesg, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(mesg, cause, enableSuppression, writableStackTrace);
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/JSSLoader.java 0000664 0000000 0000000 00000033760 14565430767 0023406 0 ustar 00root root 0000000 0000000 package org.mozilla.jss;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.Properties;
import org.mozilla.jss.util.Password;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* The JSS Loader facilitates loading JSS via the Provider interface directly,
* including from a static java.security configuration file.
*
* This replaces the previous CryptoManager.initialize(...) approach, allowing
* better control over where the JSSProvider gets loaded. In order to use this
* provider, the caller has to specify a configuration file (either via a
* String path or its contents via an InputStream). This configuration file is
* a java.util.Properties file. The following keys are understood:
*
* - nss.config_dir -- the path to the NSS DB to initialize with
* - nss.cert_prefix -- the prefix for the certificate store
* - nss.key_prefix -- the prefix for the key store
* - nss.secmod_name -- the name of the secmod file
*
* - nss.read_only -- whether to open the NSS DB read-only (default: false)
* - nss.java_only -- whether to initialize only the java portion of JSS,
* and assume that NSS is already initialized (default:
* false)
*
* - nss.pkix_verify -- whether to use PKIX for verification (default: false)
* - nss.no_cert_db -- whether to open the certificate and key databases;
* see InitializationValues for more info (default: false)
* - nss.no_mod_db -- whether to open the security module database; see
* InitializationValues for more info (default: false)
* - nss.force_open -- whether to force initializations even if the database
* cannot be opened; see InitializationValues for more
* info (default: false)
* - nss.no_root_init -- whether to look for root certificate module and load
* it; see InitializationValues for more info
* (default: false)
* - nss.optimize_space -- whether to use smaller tables and caches; see
* InitializationValues for more info (default: false)
* - nss.pk11_thread_safe -- whether to only load PKCS#11 modules that are
* thread-safe; see InitializationValues for more
* info (default: false)
* - nss.pk11_reload -- whether to ignore already initialized errors when
* loading PKCS#11 modules; see InitializationValues for
* more info (default: false)
* - nss.no_pk11_finalize -- whether to avoid calling C_Finalize on PKCS#11
* modules; see InitializationValues for more info
* (default: false)
* - nss.cooperate -- whether to cooperate with other parts of the program
* already having initialized NSS (default: false)
*
* - jss.experimental.sslengine -- whether to enable experimental SSLEngine
* support
*
* - jss.fips -- whether to switch this NSS DB into FIPS mode; allowed values
* are ENABLED (to force FIPS mode), DISABLED (to force
* non-FIPS mode), or UNCHANGED (default, to infer the value
* from the NSS DB and/or the system)
*
* - jss.ocsp.enabled -- whether or not to enable OCSP checking
* - jss.ocsp.responder.url -- URL of the OCSP responder to check
* - jss.ocsp.responder.cert_nickname -- nickname of the OCSP responder's
* certificate in the NSS DB
* - jss.ocsp.policy -- which JSS OCSP checking policy to use; allowed values
* are NONE, NORMAL, and LEAF_AND_CHAIN; refer to
* CryptoManager documentation for the difference
*
* - jss.password -- static password to use to authenticate to tokens; if
* this fails, the user will be prompted via the console
*/
public class JSSLoader {
public static Logger logger = LoggerFactory.getLogger(JSSLoader.class);
/**
* Initialize JSS from the specified path to a configuration file.
*/
public static CryptoManager init(String config_path) throws Exception {
if (config_path == null) {
String msg = "Please specify the path to the JSS configuration ";
msg += "file in the java.security provider list.";
throw new NullPointerException(msg);
}
try (FileInputStream fistream = new FileInputStream(config_path)) {
return init(fistream);
}
}
/**
* Initialize JSS from an InputStream.
*/
public static CryptoManager init(InputStream istream) throws Exception {
if (CryptoManager.isInitialized()) {
return CryptoManager.getInstance();
}
if (istream == null) {
String msg = "Please specify the JSS configuration InputStream ";
msg += "in order to properly install this provider.";
throw new NullPointerException(msg);
}
Properties config = new Properties();
config.load(istream);
InitializationValues ivs = constructIV(config);
parseFipsMode(config, ivs);
parseReadOnly(config, ivs);
parseOCSPSettings(config, ivs);
parseProviderSettings(config, ivs);
parseNSSSettings(config, ivs);
// For more information about the interactions between JSSLoader and
// CryptoManager, see docs/usage/cryptomanager.md in the source
// distribution.
CryptoManager.initialize(ivs);
CryptoManager cm = CryptoManager.getInstance();
parseOCSPPolicy(config, cm);
parsePasswords(config, cm);
parseExperimental(config);
return cm;
}
/**
* Constructs an InitializationValues from the specified properties files,
* reading only the properties required to construct a new instance.
*
* These properties are:
* - nss.config_dir
* - nss.cert_prefix
* - nss.key_prefix
* - nss.secmod_name
*/
private static InitializationValues constructIV(Properties config) {
String configDir = config.getProperty("nss.config_dir", "/etc/pki/nssdb");
String certPrefix = config.getProperty("nss.cert_prefix");
String keyPrefix = config.getProperty("nss.key_prefix");
String secmodName = config.getProperty("nss.secmod_name");
if (certPrefix == null && keyPrefix == null && secmodName == null) {
return new InitializationValues(configDir);
}
return new InitializationValues(configDir, certPrefix, keyPrefix, secmodName);
}
/**
* Updates the specified InitializationValues with the FIPS-specific
* properties.
*
* These properties are:
* - jss.fips
*/
private static void parseFipsMode(Properties config, InitializationValues ivs) {
String mode = config.getProperty("jss.fips", "unchanged");
if (mode.equalsIgnoreCase("enabled")) {
ivs.fipsMode = InitializationValues.FIPSMode.ENABLED;
} else if (mode.equalsIgnoreCase("disabled")) {
ivs.fipsMode = InitializationValues.FIPSMode.DISABLED;
} else if (mode.equalsIgnoreCase("unchanged")) {
ivs.fipsMode = InitializationValues.FIPSMode.UNCHANGED;
} else {
String msg = "Unknown value for jss.fips: " + mode + ". ";
msg += "Expecting one of ENABLED, DISABLED, or UNCHANGED.";
throw new RuntimeException(msg);
}
}
/**
* Update the specified InitializationValues with the value of the
* nss.read_only property.
*/
private static void parseReadOnly(Properties config, InitializationValues ivs) {
Boolean value = parseBoolean(config, "nss.read_only");
if (value != null) {
ivs.readOnly = value;
}
}
/**
* Update the specified InitializationValues with the value of the OCSP
* properties.
*
* These properties are:
* - jss.ocsp.enabled
* - jss.ocsp.responder.url
* - jss.ocsp.responder.cert_nickname
*/
private static void parseOCSPSettings(Properties config, InitializationValues ivs) {
Boolean enabled = parseBoolean(config, "jss.ocsp.enabled");
if (enabled != null) {
ivs.ocspCheckingEnabled = enabled;
}
String url = config.getProperty("jss.ocsp.responder.url");
ivs.ocspResponderURL = url;
String nickname = config.getProperty("jss.ocsp.responder.cert_nickname");
ivs.ocspResponderCertNickname = nickname;
}
/**
* Configure the specified InitializationValues with the correct
* provider-related properties.
*/
private static void parseProviderSettings(Properties config, InitializationValues ivs) {
// We don't want to do any of this: if the user wanted to, they'd have
// already specified this as part of the java.security configuration
// file. Plus, we're installing ourselves as the Mozilla-JSS provider.
ivs.installJSSProvider = false;
ivs.removeSunProvider = false;
ivs.installJSSProviderFirst = false;
}
/**
* Configure the specified InitializationValues with the values of various
* NSS-specific configuration values.
*
* These properties are:
* - nss.java_only
* - nss.pkix_verify
* - nss.no_cert_db
* - nss.no_mod_db
* - nss.force_open
* - nss.no_root_init
* - nss.optimize_space
* - nss.pk11_thread_safe
* - nss.pk11_reload
* - nss.no_pk11_finalize
* - nss.cooperate
*/
private static void parseNSSSettings(Properties config, InitializationValues ivs) {
Boolean initializeJavaOnly = parseBoolean(config, "nss.java_only");
if (initializeJavaOnly != null) {
ivs.initializeJavaOnly = initializeJavaOnly;
}
Boolean PKIXVerify = parseBoolean(config, "nss.pkix_verify");
if (PKIXVerify!= null) {
ivs.PKIXVerify= PKIXVerify;
}
Boolean noCertDB = parseBoolean(config, "nss.no_cert_db");
if (noCertDB != null) {
ivs.noCertDB = noCertDB;
}
Boolean noModDB = parseBoolean(config, "nss.no_mod_db");
if (noModDB != null) {
ivs.noModDB = noModDB;
}
Boolean forceOpen = parseBoolean(config, "nss.force_open");
if (forceOpen != null) {
ivs.forceOpen = forceOpen;
}
Boolean noRootInit = parseBoolean(config, "nss.no_root_init");
if (noRootInit != null) {
ivs.noRootInit = noRootInit;
}
Boolean optimizeSpace = parseBoolean(config, "nss.optimize_space");
if (optimizeSpace != null) {
ivs.optimizeSpace = optimizeSpace;
}
Boolean PK11ThreadSafe = parseBoolean(config, "nss.pk11_thread_safe");
if (PK11ThreadSafe != null) {
ivs.PK11ThreadSafe = PK11ThreadSafe;
}
Boolean PK11Reload = parseBoolean(config, "nss.pk11_reload");
if (PK11Reload != null) {
ivs.PK11Reload = PK11Reload;
}
Boolean noPK11Finalize = parseBoolean(config, "nss.no_pk11_finalize");
if (noPK11Finalize != null) {
ivs.noPK11Finalize = noPK11Finalize;
}
Boolean cooperate = parseBoolean(config, "nss.cooperate");
if (cooperate != null) {
ivs.cooperate = cooperate;
}
}
/**
* Once the CryptoManager has been initialized, update it with the value
* of the remaining OCSP propertiy, jss.ocsp.policy.
*/
private static void parseOCSPPolicy(Properties config, CryptoManager cm) {
String policy = config.getProperty("jss.ocsp.policy", "NONE");
if (policy.equalsIgnoreCase("none")) {
CryptoManager.setOCSPPolicy(CryptoManager.OCSPPolicy.NONE);
} else if (policy.equalsIgnoreCase("normal")) {
CryptoManager.setOCSPPolicy(CryptoManager.OCSPPolicy.NORMAL);
} else if (policy.equalsIgnoreCase("leaf_and_chain")) {
CryptoManager.setOCSPPolicy(CryptoManager.OCSPPolicy.LEAF_AND_CHAIN);
} else {
String msg = "Unknown value for jss.ocsp.policy: " + policy + ".";
msg += "Expecting one of NONE, NORMAL, or LEAF_AND_CHAIN.";
throw new RuntimeException(msg);
}
}
/**
* Once the CryptoManager has been initialized, update it with the correct
* PasswordCallback handler.
*
* Currently only understands a hard-coded password set via jss.password.
*/
private static void parsePasswords(Properties config, CryptoManager cm) {
String password = config.getProperty("jss.password");
if (password != null && !password.isEmpty()) {
Password pass_cb = new Password(password.toCharArray());
cm.setPasswordCallback(pass_cb);
}
}
/**
* Check for exerpimental flags.
*/
private static void parseExperimental(Properties config) {
Boolean sslengine = parseBoolean(config, "jss.experimental.sslengine");
if (sslengine != null) {
JSSProvider.ENABLE_JSSENGINE = sslengine;
}
}
/**
* Helper function to parse a boolean value at the given key name.
*
* Returns true if the value is true or yes, false if the value is
* false or no, and null if the value is empty or not present. Throws
* an exception for a malformed value. Case insensitive.
*/
private static Boolean parseBoolean(Properties config, String key_name) {
String value = config.getProperty(key_name);
if (value == null || value.isEmpty()) {
return null;
}
if (value.equalsIgnoreCase("true") || value.equalsIgnoreCase("yes")) {
return true;
}
if (value.equalsIgnoreCase("false") || value.equalsIgnoreCase("no")) {
return false;
}
String msg = "Unknown value for boolean " + key_name + ": " + value;
msg += ". Expecting true, false, or not specified.";
throw new RuntimeException(msg);
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/JSSProvider.java 0000664 0000000 0000000 00000052407 14565430767 0023771 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss;
import java.io.InputStream;
import java.security.MessageDigest;
import java.security.Provider;
import java.util.Arrays;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public final class JSSProvider extends java.security.Provider {
private static final Logger logger = LoggerFactory.getLogger(JSSProvider.class);
public static boolean ENABLE_JSSENGINE = true;
private static final long serialVersionUID = 1L;
/********************************************************************/
/* The VERSION Strings should be updated everytime a new release */
/* of JSS is generated. Note that this is done by changing */
/* cmake/JSSConfig.cmake. */
/********************************************************************/
private static final String JSS_VERSION = CryptoManager.getJSSVersion();
private static final List DEPRECATED_ALGORITHMS = Arrays.asList(
"SHA$|SHAwith|SHA1|SHA-1|SHA_1", // SHA-1 and variations thereof
"MD(2|4|5)" // MD2, MD4, MD5 and variations thereof
);
private static JSSLoader loader = new JSSLoader();
private static CryptoManager cm;
public JSSProvider() {
this(CryptoManager.isInitialized());
}
public JSSProvider(boolean initialize) {
super("Mozilla-JSS", JSS_VERSION, "Provides Signature, Message Digesting, and RNG");
if (initialize) {
initializeProvider();
}
}
public JSSProvider(String config_path) throws Exception {
this(false);
configure(config_path);
}
public JSSProvider(InputStream config) throws Exception {
this(false);
cm = JSSLoader.init(config);
initializeProvider();
}
/**
* Configure this instance of JSSProvider with the specified path
* to a JSS configuration properties file.
*
* See JSSLoader's class description for a description of the JSS
* configuration properties file and known values.
*
* If the JSSProvider is already loaded, this is a no-op.
*/
@Override
public Provider configure(String arg) {
try {
cm = JSSLoader.init(arg);
} catch (NullPointerException npe) {
throw npe;
} catch (Exception e) {
throw new RuntimeException(e.getMessage(), e);
}
initializeProvider();
return this;
}
/**
* Return the CryptoManager this instance was initialized with.
*/
public CryptoManager getCryptoManager() {
if (cm == null) {
try {
cm = CryptoManager.getInstance();
} catch (NotInitializedException nie) {}
}
return cm;
}
@Override
public Service getService(String type, String algorithm) {
if (isAlgorithmDeprecated(algorithm)) {
StackTraceElement[] stackTrace = Thread.currentThread().getStackTrace();
int i = 0;
for (i = 0; i < stackTrace.length; i++) {
if (stackTrace[i].getClassName().contains(MessageDigest.class.getCanonicalName())) {
int lineNumber = stackTrace[i + 1].getLineNumber();
String methodName = stackTrace[i + 1].getMethodName();
String className = stackTrace[i + 1].getClassName();
logger.debug(
"The {} algorithm used in {}::{}:{} is deprecated. Use a more secure algorithm.",
algorithm,
className,
methodName,
lineNumber
);
break;
}
}
}
return super.getService(type, algorithm);
}
public static boolean isAlgorithmDeprecated(String algorithm) {
for (String alg : DEPRECATED_ALGORITHMS) {
Matcher m = Pattern.compile(alg).matcher(algorithm.toUpperCase());
if (m.find()) {
return true;
}
}
return false;
}
public static List getDeprecatedAlgortihms() {
return DEPRECATED_ALGORITHMS;
}
protected void initializeProvider() {
/////////////////////////////////////////////////////////////
// Signature
/////////////////////////////////////////////////////////////
put("Signature.MD5/RSA",
"org.mozilla.jss.provider.java.security.JSSSignatureSpi$MD5RSA");
put("Alg.Alias.Signature.MD5withRSA", "MD5/RSA");
put("Signature.MD2/RSA",
"org.mozilla.jss.provider.java.security.JSSSignatureSpi$MD2RSA");
put("Signature.SHA-256/RSA",
"org.mozilla.jss.provider.java.security.JSSSignatureSpi$SHA256RSA");
put("Alg.Alias.Signature.SHA256/RSA", "SHA-256/RSA");
put("Alg.Alias.Signature.SHA256withRSA", "SHA-256/RSA");
put("Signature.RSASSA-PSS",
"org.mozilla.jss.provider.java.security.JSSSignatureSpi$RSAPSSSignature");
put("Alg.Alias.Signature.1.2.840.113549.1.1.10", "RSASSA-PSS");
put("Alg.Alias.Signature.OID.1.2.840.113549.1.1.10", "RSASSA-PSS");
put("Signature.SHA-256/RSA/PSS",
"org.mozilla.jss.provider.java.security.JSSSignatureSpi$SHA256RSAPSS");
put("Alg.Alias.Signature.SHA256withRSA/PSS","SHA-256/RSA/PSS");
put("Signature.SHA-384/RSA/PSS",
"org.mozilla.jss.provider.java.security.JSSSignatureSpi$SHA384RSAPSS");
put("Alg.Alias.Signature.SHA384withRSA/PSS","SHA-384/RSA/PSS");
put("Signature.SHA-512/RSA/PSS",
"org.mozilla.jss.provider.java.security.JSSSignatureSpi$SHA512RSAPSS");
put("Alg.Alias.Signature.SHA512withRSA/PSS","SHA-512/RSA/PSS");
put("Signature.SHA-384/RSA",
"org.mozilla.jss.provider.java.security.JSSSignatureSpi$SHA384RSA");
put("Alg.Alias.Signature.SHA384/RSA", "SHA-384/RSA");
put("Alg.Alias.Signature.SHA384withRSA", "SHA-384/RSA");
put("Signature.SHA-512/RSA",
"org.mozilla.jss.provider.java.security.JSSSignatureSpi$SHA512RSA");
put("Alg.Alias.Signature.SHA512/RSA", "SHA-512/RSA");
put("Alg.Alias.Signature.SHA512withRSA", "SHA-512/RSA");
// ECC
put("Signature.SHA256withEC",
"org.mozilla.jss.provider.java.security.JSSSignatureSpi$SHA256EC");
put("Alg.Alias.Signature.SHA256/EC", "SHA256withEC");
put("Alg.Alias.Signature.SHA-256/EC", "SHA256withEC");
put("Alg.Alias.Signature.SHA256withECDSA", "SHA256withEC"); //JCE Standard Name
put("Signature.SHA384withEC",
"org.mozilla.jss.provider.java.security.JSSSignatureSpi$SHA384EC");
put("Alg.Alias.Signature.SHA384/EC", "SHA384withEC");
put("Alg.Alias.Signature.SHA-384/EC", "SHA384withEC");
put("Alg.Alias.Signature.SHA384withECDSA", "SHA384withEC"); //JCE Standard Name
put("Signature.SHA512withEC",
"org.mozilla.jss.provider.java.security.JSSSignatureSpi$SHA512EC");
put("Alg.Alias.Signature.SHA512/EC", "SHA512withEC");
put("Alg.Alias.Signature.SHA-512/EC", "SHA512withEC");
put("Alg.Alias.Signature.SHA512withECDSA", "SHA512withEC"); //JCE Standard Name
/////////////////////////////////////////////////////////////
// Message Digesting
/////////////////////////////////////////////////////////////
put("MessageDigest.MD2",
"org.mozilla.jss.provider.java.security.JSSMessageDigestSpi$MD2");
put("MessageDigest.MD5",
"org.mozilla.jss.provider.java.security.JSSMessageDigestSpi$MD5");
put("MessageDigest.SHA-256",
"org.mozilla.jss.provider.java.security.JSSMessageDigestSpi$SHA256");
put("MessageDigest.SHA-384",
"org.mozilla.jss.provider.java.security.JSSMessageDigestSpi$SHA384");
put("MessageDigest.SHA-512",
"org.mozilla.jss.provider.java.security.JSSMessageDigestSpi$SHA512");
put("Alg.Alias.MessageDigest.SHA256", "SHA-256");
put("Alg.Alias.MessageDigest.SHA384", "SHA-384");
put("Alg.Alias.MessageDigest.SHA512", "SHA-512");
/////////////////////////////////////////////////////////////
// SecureRandom
/////////////////////////////////////////////////////////////
put("SecureRandom.pkcs11prng",
"org.mozilla.jss.provider.java.security.JSSSecureRandomSpi");
/////////////////////////////////////////////////////////////
// KeyPairGenerator
/////////////////////////////////////////////////////////////
put("KeyPairGenerator.RSA",
"org.mozilla.jss.provider.java.security.JSSKeyPairGeneratorSpi$RSA");
put("KeyPairGenerator.DSA",
"org.mozilla.jss.provider.java.security.JSSKeyPairGeneratorSpi$DSA");
put("KeyPairGenerator.EC",
"org.mozilla.jss.provider.java.security.JSSKeyPairGeneratorSpi$EC");
/////////////////////////////////////////////////////////////
// KeyFactory
/////////////////////////////////////////////////////////////
put("KeyFactory.RSA",
"org.mozilla.jss.provider.java.security.KeyFactorySpi1_2");
put("KeyFactory.DSA",
"org.mozilla.jss.provider.java.security.KeyFactorySpi1_2");
put("KeyFactory.EC",
"org.mozilla.jss.provider.java.security.KeyFactorySpi1_2");
/////////////////////////////////////////////////////////////
// KeyStore
/////////////////////////////////////////////////////////////
put("KeyStore.PKCS11",
"org.mozilla.jss.provider.java.security.JSSKeyStoreSpi");
/////////////////////////////////////////////////////////////
// AlgorithmParameters
/////////////////////////////////////////////////////////////
put("AlgorithmParameters.IvAlgorithmParameters",
"org.mozilla.jss.provider.java.security.IvAlgorithmParameters");
put("AlgorithmParameters.RC2AlgorithmParameters",
"org.mozilla.jss.provider.java.security.RC2AlgorithmParameters");
put("AlgorithmParameters.RSAPSSAlgorithmParameters",
"org.mozilla.jss.provider.java.security.RSAPSSAlgorithmParameters");
/////////////////////////////////////////////////////////////
// Cipher
/////////////////////////////////////////////////////////////
put("Cipher.DES",
"org.mozilla.jss.provider.javax.crypto.JSSCipherSpi$DES");
put("Cipher.DESede",
"org.mozilla.jss.provider.javax.crypto.JSSCipherSpi$DESede");
put("Alg.Alias.Cipher.DES3", "DESede");
put("Cipher.AES",
"org.mozilla.jss.provider.javax.crypto.JSSCipherSpi$AES");
put("Cipher.RC4",
"org.mozilla.jss.provider.javax.crypto.JSSCipherSpi$RC4");
put("Cipher.RSA",
"org.mozilla.jss.provider.javax.crypto.JSSCipherSpi$RSA");
put("Cipher.RC2",
"org.mozilla.jss.provider.javax.crypto.JSSCipherSpi$RC2");
/////////////////////////////////////////////////////////////
// KeyGenerator
/////////////////////////////////////////////////////////////
String kg_spi = "org.mozilla.jss.provider.javax.crypto.JSSKeyGeneratorSpi";
put("KeyGenerator.DES", kg_spi + "$DES");
put("KeyGenerator.DESede", kg_spi + "$DESede");
put("Alg.Alias.KeyGenerator.DES3", "DESede");
put("KeyGenerator.AES", kg_spi + "$AES");
put("KeyGenerator.RC4", kg_spi + "$RC4");
put("KeyGenerator.RC2", kg_spi + "$RC2");
put("KeyGenerator.HmacSHA1", kg_spi + "$HmacSHA1");
put("KeyGenerator.PBAHmacSHA1", kg_spi + "$PBAHmacSHA1");
put("KeyGenerator.PBESHA256Hmac", kg_spi + "$PBESHA256Hmac");
put("KeyGenerator.PBESHA384Hmac", kg_spi + "$PBESHA384Hmac");
put("KeyGenerator.PBESHA512Hmac", kg_spi + "$PBESHA512Hmac");
put("KeyGenerator.HmacSHA256", kg_spi + "$HmacSHA256");
put("KeyGenerator.HmacSHA384", kg_spi + "$HmacSHA384");
put("KeyGenerator.HmacSHA512", kg_spi + "$HmacSHA512");
// KBKDF: Counter
put("KeyGenerator.KbkdfCounter", kg_spi + "$KbkdfCounter");
put("Alg.Alias.KeyGenerator.KBKDF-Counter", "KbkdfCounter");
put("Alg.Alias.KeyGenerator.SP800-108-KDF-Counter", "KbkdfCounter");
put("Alg.Alias.KeyGenerator.SP800-108-Counter", "KbkdfCounter");
put("Alg.Alias.KeyGenerator.CounterKbkdf", "KbkdfCounter");
// KBKDF: Counter (data)
put("KeyGenerator.KbkdfCounterData", kg_spi + "$KbkdfCounterData");
put("Alg.Alias.KeyGenerator.KBKDF-Counter-Data", "KbkdfCounterData");
put("Alg.Alias.KeyGenerator.SP800-108-KDF-Counter-Data", "KbkdfCounterData");
put("Alg.Alias.KeyGenerator.SP800-108-Counter-Data", "KbkdfCounterData");
put("Alg.Alias.KeyGenerator.CounterKbkdf-Data", "KbkdfCounterData");
// KBKDF: Feedback
put("KeyGenerator.KbkdfFeedback", kg_spi + "$KbkdfFeedback");
put("Alg.Alias.KeyGenerator.KBKDF-Feedback", "KbkdfFeedback");
put("Alg.Alias.KeyGenerator.SP800-108-KDF-Feedback", "KbkdfFeedback");
put("Alg.Alias.KeyGenerator.SP800-108-Feedback", "KbkdfFeedback");
put("Alg.Alias.KeyGenerator.FeedbackKbkdf", "KbkdfFeedback");
// KBKDF: Feedback (data)
put("KeyGenerator.KbkdfFeedbackData", kg_spi + "$KbkdfFeedbackData");
put("Alg.Alias.KeyGenerator.KBKDF-Feedback-Data", "KbkdfFeedbackData");
put("Alg.Alias.KeyGenerator.SP800-108-KDF-Feedback-Data", "KbkdfFeedbackData");
put("Alg.Alias.KeyGenerator.SP800-108-Feedback-Data", "KbkdfFeedbackData");
put("Alg.Alias.KeyGenerator.FeedbackKbkdf-Data", "KbkdfFeedbackData");
// KBKDF: Double Pipeline -- sometimes Pipeline KBKDF
put("KeyGenerator.KbkdfDoublePipeline", kg_spi + "$KbkdfDoublePipeline");
put("Alg.Alias.KeyGenerator.KBKDF-DoublePipeline", "KbkdfDoublePipeline");
put("Alg.Alias.KeyGenerator.SP800-108-KDF-DoublePipeline", "KbkdfDoublePipeline");
put("Alg.Alias.KeyGenerator.SP800-108-DoublePipeline", "KbkdfDoublePipeline");
put("Alg.Alias.KeyGenerator.DoublePipelineKbkdf", "KbkdfDoublePipeline");
put("Alg.Alias.KeyGenerator.KbkdfPipeline", "KbkdfDoublePipeline");
put("Alg.Alias.KeyGenerator.KBKDF-Pipeline", "KbkdfDoublePipeline");
put("Alg.Alias.KeyGenerator.SP800-108-KDF-Pipeline", "KbkdfDoublePipeline");
put("Alg.Alias.KeyGenerator.SP800-108-Pipeline", "KbkdfDoublePipeline");
put("Alg.Alias.KeyGenerator.PipelineKbkdf", "KbkdfDoublePipeline");
// KBKDF: Double Pipeline (data) -- sometimes Pipeline KBKDF (data)
put("KeyGenerator.KbkdfDoublePipelineData", kg_spi + "$KbkdfDoublePipelineData");
put("Alg.Alias.KeyGenerator.KBKDF-DoublePipeline-Data", "KbkdfDoublePipelineData");
put("Alg.Alias.KeyGenerator.SP800-108-KDF-DoublePipeline-Data", "KbkdfDoublePipelineData");
put("Alg.Alias.KeyGenerator.SP800-108-DoublePipeline-Data", "KbkdfDoublePipelineData");
put("Alg.Alias.KeyGenerator.DoublePipelineKbkdf-Data", "KbkdfDoublePipelineData");
put("Alg.Alias.KeyGenerator.KbkdfPipelineData", "KbkdfDoublePipelineData");
put("Alg.Alias.KeyGenerator.KBKDF-Pipeline-Data", "KbkdfDoublePipelineData");
put("Alg.Alias.KeyGenerator.SP800-108-KDF-Pipeline-Data", "KbkdfDoublePipelineData");
put("Alg.Alias.KeyGenerator.SP800-108-Pipeline-Data", "KbkdfDoublePipelineData");
put("Alg.Alias.KeyGenerator.PipelineKbkdf-Data", "KbkdfDoublePipelineData");
/////////////////////////////////////////////////////////////
// SecretKeyFactory
/////////////////////////////////////////////////////////////
put("SecretKeyFactory.GenericSecret", "org.mozilla.jss.provider.javax.crypto.JSSSecretKeyFactorySpi$GenericSecret");
put("Alg.Alias.SecretKeyFactory.GENERIC_SECRET", "GenericSecret");
put("SecretKeyFactory.DES",
"org.mozilla.jss.provider.javax.crypto.JSSSecretKeyFactorySpi$DES");
put("SecretKeyFactory.DESede",
"org.mozilla.jss.provider.javax.crypto.JSSSecretKeyFactorySpi$DESede");
put("Alg.Alias.SecretKeyFactory.DES3", "DESede");
put("SecretKeyFactory.AES",
"org.mozilla.jss.provider.javax.crypto.JSSSecretKeyFactorySpi$AES");
put("SecretKeyFactory.RC4",
"org.mozilla.jss.provider.javax.crypto.JSSSecretKeyFactorySpi$RC4");
put("SecretKeyFactory.RC2",
"org.mozilla.jss.provider.javax.crypto.JSSSecretKeyFactorySpi$RC2");
put("SecretKeyFactory.HmacSHA1",
"org.mozilla.jss.provider.javax.crypto.JSSSecretKeyFactorySpi$HmacSHA1");
put("SecretKeyFactory.PBAHmacSHA1",
"org.mozilla.jss.provider.javax.crypto.JSSSecretKeyFactorySpi$PBAHmacSHA1");
put("SecretKeyFactory.HmacSHA256",
"org.mozilla.jss.provider.javax.crypto.JSSSecretKeyFactorySpi$HmacSHA256");
put("SecretKeyFactory.HmacSHA384",
"org.mozilla.jss.provider.javax.crypto.JSSSecretKeyFactorySpi$HmacSHA384");
put("SecretKeyFactory.HmacSHA512",
"org.mozilla.jss.provider.javax.crypto.JSSSecretKeyFactorySpi$HmacSHA512");
put("SecretKeyFactory.PBEWithMD5AndDES",
"org.mozilla.jss.provider.javax.crypto.JSSSecretKeyFactorySpi$PBE_MD5_DES_CBC");
put("SecretKeyFactory.PBEWithSHA1AndDES",
"org.mozilla.jss.provider.javax.crypto.JSSSecretKeyFactorySpi$PBE_SHA1_DES_CBC");
put("SecretKeyFactory.PBEWithSHA1AndDESede",
"org.mozilla.jss.provider.javax.crypto.JSSSecretKeyFactorySpi$PBE_SHA1_DES3_CBC");
put("Alg.Alias.SecretKeyFactory.PBEWithSHA1AndDES3", "PBEWithSHA1AndDESede");
put("SecretKeyFactory.PBEWithSHA1And128RC4",
"org.mozilla.jss.provider.javax.crypto.JSSSecretKeyFactorySpi$PBE_SHA1_RC4_128");
/////////////////////////////////////////////////////////////
// MAC
/////////////////////////////////////////////////////////////
put("Mac.HmacSHA1",
"org.mozilla.jss.provider.javax.crypto.JSSMacSpi$HmacSHA1");
put("Alg.Alias.Mac.Hmac-SHA1", "HmacSHA1");
put("Mac.HmacSHA256",
"org.mozilla.jss.provider.javax.crypto.JSSMacSpi$HmacSHA256");
put("Alg.Alias.Mac.Hmac-SHA256", "HmacSHA256");
put("Mac.HmacSHA384",
"org.mozilla.jss.provider.javax.crypto.JSSMacSpi$HmacSHA384");
put("Alg.Alias.Mac.Hmac-SHA384", "HmacSHA384");
put("Mac.HmacSHA512",
"org.mozilla.jss.provider.javax.crypto.JSSMacSpi$HmacSHA512");
put("Mac.CmacAES", "org.mozilla.jss.provider.javax.crypto.JSSMacSpi$CmacAES");
put("Alg.Alias.Mac.Hmac-SHA512", "HmacSHA512");
put("Alg.Alias.Mac.SHA-256-HMAC", "HmacSHA256");
put("Alg.Alias.Mac.SHA-384-HMAC", "HmacSHA384");
put("Alg.Alias.Mac.SHA-512-HMAC", "HmacSHA512");
put("Alg.Alias.Mac.AES-128-CMAC", "CmacAES");
put("Alg.Alias.Mac.AES-192-CMAC", "CmacAES");
put("Alg.Alias.Mac.AES-256-CMAC", "CmacAES");
put("Alg.Alias.Mac.CmacAES128", "CmacAES");
put("Alg.Alias.Mac.CmacAES192", "CmacAES");
put("Alg.Alias.Mac.CmacAES256", "CmacAES");
put("Alg.Alias.Mac.AES_CMAC", "CmacAES");
put("Alg.Alias.Mac.CMAC_AES", "CmacAES");
/////////////////////////////////////////////////////////////
// KeyManagerFactory
/////////////////////////////////////////////////////////////
put("KeyManagerFactory.NssX509",
"org.mozilla.jss.provider.javax.crypto.JSSKeyManagerFactory");
put("Alg.Alias.KeyManagerFactory.SunX509", "NssX509");
put("Alg.Alias.KeyManagerFactory.PKIX", "SunX509");
/////////////////////////////////////////////////////////////
// TrustManagerFactory
/////////////////////////////////////////////////////////////
put("TrustManagerFactory.NssX509",
"org.mozilla.jss.provider.javax.crypto.JSSTrustManagerFactory");
put("Alg.Alias.TrustManagerFactory.SunX509", "NssX509");
put("Alg.Alias.TrustManagerFactory.PKIX", "NssX509");
put("Alg.Alias.TrustManagerFactory.X509", "NssX509");
put("Alg.Alias.TrustManagerFactory.X.509", "NssX509");
/////////////////////////////////////////////////////////////
// TLS
/////////////////////////////////////////////////////////////
if (ENABLE_JSSENGINE) {
put("SSLContext.Default", "org.mozilla.jss.provider.javax.net.JSSContextSpi");
put("SSLContext.SSL", "org.mozilla.jss.provider.javax.net.JSSContextSpi");
put("SSLContext.TLS", "org.mozilla.jss.provider.javax.net.JSSContextSpi");
put("SSLContext.TLSv1.1", "org.mozilla.jss.provider.javax.net.JSSContextSpi$TLSv11");
put("SSLContext.TLSv1.2", "org.mozilla.jss.provider.javax.net.JSSContextSpi$TLSv12");
put("SSLContext.TLSv1.3", "org.mozilla.jss.provider.javax.net.JSSContextSpi$TLSv13");
}
}
@Override
public String toString() {
return "Mozilla-JSS version: " + JSS_VERSION;
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/KeyDatabaseException.java 0000664 0000000 0000000 00000001546 14565430767 0025651 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss;
/**
* This exception is thrown if the key database does not exist, or if
* an error occurs while opening it.
*/
public class KeyDatabaseException extends java.lang.Exception {
private static final long serialVersionUID = 1L;
public KeyDatabaseException() {}
public KeyDatabaseException(String mesg) {
super(mesg);
}
public KeyDatabaseException(String mesg, Throwable cause) {
super(mesg, cause);
}
public KeyDatabaseException(String mesg, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(mesg, cause, enableSuppression, writableStackTrace);
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/NicknameConflictException.java 0000664 0000000 0000000 00000000537 14565430767 0026702 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss;
public final class NicknameConflictException extends Exception {
private static final long serialVersionUID = 1L;
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/NoSuchTokenException.java 0000664 0000000 0000000 00000001440 14565430767 0025665 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss;
/**
* Thrown if a token cannot be found.
*/
public class NoSuchTokenException extends java.lang.Exception {
private static final long serialVersionUID = 1L;
public NoSuchTokenException() {}
public NoSuchTokenException(String mesg) {
super(mesg);
}
public NoSuchTokenException(String mesg, Throwable cause) {
super(mesg, cause);
}
public NoSuchTokenException(String mesg, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(mesg, cause, enableSuppression, writableStackTrace);
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/NotInitializedException.java 0000664 0000000 0000000 00000000535 14565430767 0026417 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss;
public final class NotInitializedException extends Exception {
private static final long serialVersionUID = 1L;
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/SecretDecoderRing/ 0000775 0000000 0000000 00000000000 14565430767 0024277 5 ustar 00root root 0000000 0000000 jss-5.5.0/base/src/main/java/org/mozilla/jss/SecretDecoderRing/Decryptor.java 0000664 0000000 0000000 00000006621 14565430767 0027122 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.SecretDecoderRing;
import java.security.GeneralSecurityException;
import java.security.InvalidKeyException;
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.spec.IvParameterSpec;
import org.mozilla.jss.CryptoManager;
import org.mozilla.jss.NotInitializedException;
import org.mozilla.jss.asn1.ASN1Util;
import org.mozilla.jss.asn1.InvalidBERException;
import org.mozilla.jss.crypto.CryptoToken;
import org.mozilla.jss.crypto.EncryptionAlgorithm;
import org.mozilla.jss.crypto.TokenException;
/**
* Decrypts data with the SecretDecoderRing.
*/
public class Decryptor {
private CryptoToken token;
private KeyManager keyManager;
/**
* Creates a Decryptor for use with the given CryptoToken.
*/
public Decryptor(CryptoToken token) {
this.token = token;
this.keyManager = new KeyManager(token);
}
/**
* Decrypts the given ciphertext. It must have been created previously
* with the SecretDecoderRing, either the JSS version or the NSS version.
* The key used for decryption must exist on the token that was passed
* into the constructor. The token will be searched for a key whose keyID
* matches the keyID in the encoded SecretDecoderRing result.
*
* @param ciphertext A DER-encoded Encoding object, created from a previous
* call to Encryptor.encrypt(), or with the NSS SecretDecoderRing.
* @return The decrypted plaintext.
* @throws InvalidKeyException If no key can be found with the matching
* keyID.
*/
public byte[] decrypt(byte[] ciphertext)
throws NotInitializedException,
GeneralSecurityException, TokenException
{
CryptoManager cm = CryptoManager.getInstance();
CryptoToken savedToken = cm.getThreadToken();
try {
cm.setThreadToken(token);
//
// decode ASN1
//
Encoding encoding = (Encoding)
ASN1Util.decode(Encoding.getTemplate(), ciphertext);
//
// lookup the algorithm
//
EncryptionAlgorithm alg = EncryptionAlgorithm.fromOID(
encoding.getEncryptionOID() );
//
// Lookup the key
//
SecretKey key = keyManager.lookupKey(alg, encoding.getKeyID());
if( key == null ) {
throw new InvalidKeyException("No matching key found");
}
//
// do the decryption
//
IvParameterSpec ivSpec = new IvParameterSpec(encoding.getIv());
Cipher cipher = Cipher.getInstance(alg.toString(),
Encryptor.PROVIDER);
cipher.init(Cipher.DECRYPT_MODE, key, ivSpec);
byte[] paddedPtext = cipher.doFinal(encoding.getCiphertext());
return org.mozilla.jss.crypto.Cipher.unPad(paddedPtext,
alg.getBlockSize() );
} catch(InvalidBERException ibe) {
throw new GeneralSecurityException(ibe.toString());
} catch(IllegalStateException ise) {
throw new GeneralSecurityException(ise.toString());
} finally {
cm.setThreadToken(savedToken);
}
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/SecretDecoderRing/Encoding.java 0000664 0000000 0000000 00000007173 14565430767 0026700 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.SecretDecoderRing;
import org.mozilla.jss.asn1.*;
import org.mozilla.jss.pkix.primitive.*;
import java.io.*;
/**
* An ASN.1 class for encoding the SecretDecoderRing result.
* This class is used internally by the SecretDecoderRing.
* You need not use this class directly in order to use the SecretDecoderRing.
*/
public class Encoding implements ASN1Value {
private SEQUENCE seq = new SEQUENCE();
private byte[] iv;
private OBJECT_IDENTIFIER encOID;
private byte[] ctext;
private byte[] keyID;
public Encoding(byte[] keyID, byte[] iv, OBJECT_IDENTIFIER encOID,
byte[] ctext)
{
this.keyID = keyID;
this.iv = iv;
this.encOID = encOID;
this.ctext = ctext;
AlgorithmIdentifier algID = new AlgorithmIdentifier(
encOID, new OCTET_STRING(iv) );
seq.addElement(new OCTET_STRING(keyID));
seq.addElement(algID);
seq.addElement(new OCTET_STRING(ctext));
}
public byte[] getKeyID() {
return keyID;
}
public byte[] getIv() {
return iv;
}
public OBJECT_IDENTIFIER getEncryptionOID() {
return encOID;
}
public byte[] getCiphertext() {
return ctext;
}
public static final Tag TAG = SEQUENCE.TAG;
@Override
public Tag getTag() {
return TAG;
}
@Override
public void encode(OutputStream ostream) throws IOException {
encode(TAG, ostream);
}
@Override
public void encode(Tag implicitTag, OutputStream ostream)
throws IOException
{
seq.encode(implicitTag, ostream);
}
private static final Template templateInstance = new Template();
public static Template getTemplate() {
return templateInstance;
}
/**
* An ASN.1 class for decoding the SecretDecoderRing result.
* This class is used internally by the SecretDecoderRing.
* You need not use this class directly in order to use the
* SecretDecoderRing.
*/
public static class Template extends SEQUENCE.Template {
private SEQUENCE.Template template;
public Template() {
template = new SEQUENCE.Template();
template.addElement(OCTET_STRING.getTemplate() );
template.addElement(AlgorithmIdentifier.getTemplate() );
template.addElement(OCTET_STRING.getTemplate() );
}
@Override
public boolean tagMatch(Tag tag) {
return TAG.equals(tag);
}
@Override
public ASN1Value decode(InputStream istream)
throws IOException, InvalidBERException
{
return decode(TAG, istream);
}
@Override
public ASN1Value decode(Tag implicitTag, InputStream istream)
throws IOException, InvalidBERException
{
SEQUENCE seq = (SEQUENCE) template.decode(implicitTag, istream);
OCTET_STRING keyID = (OCTET_STRING) seq.elementAt(0);
AlgorithmIdentifier algID = (AlgorithmIdentifier)
seq.elementAt(1);
OCTET_STRING ivOS = (OCTET_STRING)
((ANY)algID.getParameters()).decodeWith(
OCTET_STRING.getTemplate());
OCTET_STRING ctextOS = (OCTET_STRING)seq.elementAt(2);
return new Encoding(keyID.toByteArray(),
ivOS.toByteArray(), algID.getOID(),
ctextOS.toByteArray());
}
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/SecretDecoderRing/Encryptor.java 0000664 0000000 0000000 00000007611 14565430767 0027134 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.SecretDecoderRing;
import java.security.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import org.mozilla.jss.asn1.*;
import org.mozilla.jss.CryptoManager;
import org.mozilla.jss.NotInitializedException;
import org.mozilla.jss.crypto.CryptoToken;
import org.mozilla.jss.crypto.EncryptionAlgorithm;
import org.mozilla.jss.crypto.TokenException;
/**
* Encrypts data with the SecretDecoderRing.
*/
public class Encryptor {
private CryptoToken token;
private byte[] keyID;
private SecretKey key;
private EncryptionAlgorithm alg;
private KeyManager keyManager;
/**
* The default encryption algorithm, currently DES3_CBC.
*/
public static final EncryptionAlgorithm DEFAULT_ENCRYPTION_ALG
= EncryptionAlgorithm.DES3_CBC;
static final String PROVIDER = "Mozilla-JSS";
static final String RNG_ALG = "pkcs11prng";
/**
* Creates an Encryptor on the given CryptoToken, using the key with
* the given keyID and algorithm
* @param token The CryptoToken to use for encryption. The key must
* reside on this token.
* @param keyID The keyID of the key to use for encryption. This key
* must have been generated on this token with KeyManager.
* @param alg The EncryptionAlgorithm this key will be used for.
* @throws InvalidKeyException If no key exists on this token with this
* keyID.
*/
public Encryptor(CryptoToken token, byte[] keyID, EncryptionAlgorithm alg)
throws TokenException, InvalidKeyException
{
this.token = token;
this.keyID = keyID;
this.alg = alg;
this.keyManager = new KeyManager(token);
// make sure this key exists on the token
key = keyManager.lookupKey(alg, keyID);
if( key == null ) {
throw new InvalidKeyException("Key not found");
}
// make sure key matches algorithm
// !!! not sure how to do this
}
/**
* Encrypts a byte array.
* @param plaintext The plaintext bytes to be encrypted.
* @return The ciphertext. This is actually a DER-encoded Encoding
* object. It contains the keyID, AlgorithmIdentifier, and the encrypted
* plaintext. It is compatible with the SDRResult created by NSS's
* SecretDecoderRing.
*/
public byte[] encrypt(byte[] plaintext) throws
NotInitializedException,
GeneralSecurityException,
InvalidBERException
{
CryptoManager cm = CryptoManager.getInstance();
CryptoToken savedToken = cm.getThreadToken();
try {
cm.setThreadToken(token);
//
// generate an IV
//
byte[] iv = new byte[alg.getIVLength()];
SecureRandom rng = SecureRandom.getInstance(RNG_ALG,
PROVIDER);
rng.nextBytes(iv);
IvParameterSpec ivSpec = new IvParameterSpec(iv);
//
// do the encryption
//
Cipher cipher = Cipher.getInstance(alg.toString(),PROVIDER);
cipher.init(Cipher.ENCRYPT_MODE, key, ivSpec);
byte[] paddedPtext =
org.mozilla.jss.crypto.Cipher.pad(
plaintext, alg.getBlockSize() );
byte[] rawCtext = cipher.doFinal(paddedPtext);
//
// package the encrypted content and IV
//
Encoding encoding =
new Encoding(keyID, iv, alg.toOID(), rawCtext);
return ASN1Util.encode(encoding);
} catch(IllegalStateException ise ) {
throw new GeneralSecurityException(ise.toString());
} finally {
cm.setThreadToken(savedToken);
}
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/SecretDecoderRing/KeyManager.java 0000664 0000000 0000000 00000025201 14565430767 0027165 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.SecretDecoderRing;
import java.security.*;
import javax.crypto.*;
import org.mozilla.jss.crypto.*;
/**
* Creates, finds, and deletes keys for SecretDecoderRing.
*/
public class KeyManager {
private static final int KEYID_LEN = 16;
private static final String RNG_ALG = "pkcs11prng";
private static final String RNG_PROVIDER = "Mozilla-JSS";
/**
* The default key generation algorithm, currently DES3.
*/
public static final KeyGenAlgorithm DEFAULT_KEYGEN_ALG =
KeyGenAlgorithm.DES3;
/**
* The default key size (in bytes). This is only relevant for algorithms
* with variable-length keys, such as AES.
*/
public static final int DEFAULT_KEYSIZE = 0;
private CryptoToken token;
/**
* Creates a new KeyManager using the given CryptoToken.
* @param token The token on which this KeyManager operates.
*/
public KeyManager(CryptoToken token) {
if( token == null ) {
throw new NullPointerException("token is null");
}
this.token = token;
}
/**
* Generates an SDR key with the default algorithm and key size.
* The default algorithm is stored in the constant DEFAULT_KEYGEN_ALG.
* The default key size is stored in the constant DEFAULT_KEYSIZE.
* @return The keyID of the generated key. A random keyID will be chosen
* that is not currently used on the token. The keyID must be stored
* by the application in order to use this key for encryption in the
* future.
*/
public byte[] generateKey() throws TokenException {
return generateKey(DEFAULT_KEYGEN_ALG, DEFAULT_KEYSIZE);
}
/**
* Generates an SDR key with the given algorithm and key size.
* @param keySize Length of key in bytes. This is only relevant for
* algorithms that take more than one key size. Otherwise it can just
* be set to 0.
* @return The keyID of the generated key. A random keyID will be chosen
* that is not currently used on the token. The keyID must be stored
* by the application in order to use this key for encryption in the
* future.
*/
public byte[] generateKey(KeyGenAlgorithm alg, int keySize)
throws TokenException
{
if( alg == null ) {
throw new NullPointerException("alg is null");
}
byte[] keyID = generateUnusedKeyID();
generateKeyNative(token, alg, keyID, keySize);
return keyID;
}
/**
* @param keySize Key length in bytes.
*/
private native void generateKeyNative(CryptoToken token,
KeyGenAlgorithm alg, byte[] keyID, int keySize);
/**
* Generates an SDR key with the default algorithm and key size.
* and names it with the specified nickname.
* The default algorithm is stored in the constant DEFAULT_KEYGEN_ALG.
* The default key size is stored in the constant DEFAULT_KEYSIZE.
* @param nickname the name of the symmetric key. Duplicate keynames
* will be checked for, and are not allowed.
* @return The keyID of the generated key. A random keyID will be chosen
* that is not currently used on the token. The keyID must be stored
* by the application in order to use this key for encryption in the
* future.
*/
public byte[] generateUniqueNamedKey(String nickname)
throws TokenException {
return generateUniqueNamedKey(DEFAULT_KEYGEN_ALG, DEFAULT_KEYSIZE,
nickname);
}
/**
* Generates an SDR key with the given algorithm, key size, and nickname.
* @param alg The algorithm that this key will be used for.
* This is necessary because it will be stored along with the
* key for later use by the security library.
* @param keySize Length of key in bytes. This is only relevant for
* algorithms that take more than one key size. Otherwise it can just
* be set to 0.
* @param nickname the name of the symmetric key. Duplicate keynames
* will be checked for, and are not allowed.
* @return The keyID of the generated key. A random keyID will be chosen
* that is not currently used on the token. The keyID must be stored
* by the application in order to use this key for encryption in the
* future.
*/
public byte[] generateUniqueNamedKey(KeyGenAlgorithm alg, int keySize,
String nickname)
throws TokenException
{
// always strip all preceding/trailing whitespace
// from passed-in String parameters
if( nickname != null ) {
nickname = nickname.trim();
}
if( alg == null ) {
throw new NullPointerException("alg is null");
}
// disallow duplicates (i. e. - symmetric keys with the same name)
if( uniqueNamedKeyExists(nickname) ) {
throw new NullPointerException("duplicate symmetric key");
}
byte[] keyID = generateUnusedKeyID();
generateUniqueNamedKeyNative(token, alg, keyID, keySize, nickname);
return keyID;
}
/**
* @param keySize Key length in bytes.
* @param nickname the name of the symmetric key. Duplicate keynames
* will be checked for, and are not allowed.
*/
private native void generateUniqueNamedKeyNative(CryptoToken token,
KeyGenAlgorithm alg, byte[] keyID, int keySize, String nickname);
/**
* Generates a key ID that is currently unused on this token.
* The caller is responsible for synchronization issues that may arise
* if keys are generated by different threads.
*/
private byte[] generateUnusedKeyID() throws TokenException {
try {
SecureRandom rng = SecureRandom.getInstance(RNG_ALG, RNG_PROVIDER);
byte[] keyID = new byte[KEYID_LEN];
do {
rng.nextBytes(keyID);
} while( keyExists(keyID) );
return keyID;
} catch(NoSuchAlgorithmException nsae) {
throw new RuntimeException("No such algorithm: " + RNG_ALG);
} catch(NoSuchProviderException nspe) {
throw new RuntimeException("No such provider: " + RNG_PROVIDER);
}
}
private boolean keyExists(byte[] keyid) throws TokenException {
return (lookupKey(Encryptor.DEFAULT_ENCRYPTION_ALG, keyid) != null);
}
/**
* Looks up the key on this token with the given algorithm and key ID.
* @param alg The algorithm that this key will be used for.
* This is necessary because it will be stored along with the
* key for later use by the security library. It should match
* the actual algorithm of the key you are looking for. If you
* pass in a different algorithm and try to use the key that is returned,
* the results are undefined.
* @return The key, or null
if the key is not found.
*/
public SecretKey lookupKey(EncryptionAlgorithm alg, byte[] keyid)
throws TokenException
{
if( alg == null || keyid == null ) {
throw new NullPointerException();
}
SymmetricKey k = lookupKeyNative(token, alg, keyid);
if( k == null ) {
return null;
} else {
return new SecretKeyFacade(k);
}
}
private native SymmetricKey lookupKeyNative(CryptoToken token,
EncryptionAlgorithm alg, byte[] keyid) throws TokenException;
public boolean uniqueNamedKeyExists(String nickname)
throws TokenException
{
return (lookupUniqueNamedKey(Encryptor.DEFAULT_ENCRYPTION_ALG,
nickname) != null);
}
/**
* Looks up the key on this token with the given algorithm and nickname.
* @param alg The algorithm that this key will be used for.
* This is necessary because it will be stored along with the
* key for later use by the security library. It should match
* the actual algorithm of the key you are looking for. If you
* pass in a different algorithm and try to use the key that is returned,
* the results are undefined.
* @param nickname the name of the symmetric key. Duplicate keynames
* will be checked for, and are not allowed.
* @return The key, or null
if the key is not found.
*/
public SecretKey lookupUniqueNamedKey(EncryptionAlgorithm alg,
String nickname)
throws TokenException
{
// always strip all preceding/trailing whitespace
// from passed-in String parameters
if( nickname != null ) {
nickname = nickname.trim();
}
if( alg == null || nickname == null || nickname.equals("") ) {
throw new NullPointerException();
}
SymmetricKey k = lookupUniqueNamedKeyNative(token, alg, nickname);
if( k == null ) {
return null;
} else {
return new SecretKeyFacade(k);
}
}
private native SymmetricKey lookupUniqueNamedKeyNative(CryptoToken token,
EncryptionAlgorithm alg, String nickname) throws TokenException;
/**
* Deletes the key with the given keyID from this token.
* @throws InvalidKeyException If the key does not exist on this token.
*/
public void deleteKey(byte[] keyID) throws TokenException,
InvalidKeyException
{
deleteKey(lookupKey(Encryptor.DEFAULT_ENCRYPTION_ALG, keyID));
}
/**
* If it exists, delete the key with the specified nickname from this
* token.
*/
public void deleteUniqueNamedKey(String nickname) throws TokenException,
InvalidKeyException
{
// only delete this symmetric key if it exists
if( uniqueNamedKeyExists(nickname) ) {
deleteKey(lookupUniqueNamedKey(Encryptor.DEFAULT_ENCRYPTION_ALG,
nickname));
}
}
/**
* Deletes this key from this token.
* @throws InvalidKeyException If the key does not reside on this token,
* or is not a JSS key.
*/
public void deleteKey(SecretKey key) throws TokenException,
InvalidKeyException
{
if( key == null ) {
throw new NullPointerException();
}
if( ! (key instanceof SecretKeyFacade) ) {
throw new InvalidKeyException("Key must be a JSS key");
}
deleteKeyNative(token, ((SecretKeyFacade)key).key);
}
private native void deleteKeyNative(CryptoToken token, SymmetricKey key)
throws TokenException;
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/SecretDecoderRing/package.html 0000664 0000000 0000000 00000001201 14565430767 0026552 0 ustar 00root root 0000000 0000000
org.mozilla.jss.SecretDecoderRing
A facility for encrypting and decrypting small amounts of data with
a symmetric key. This is most commonly used for encrypting password files
to implement single sign-on.
KeyManager is used to create, lookup, and delete the symmetric keys used
for SecretDecoderRing. Encryptor is used to encrypt data. Decryptor is used
to decrypt data that was previously encrypted with Encryptor. Encoding
and Encoding.Template are used internally, but they were made public
because they may occasionally be useful to applications.
jss-5.5.0/base/src/main/java/org/mozilla/jss/UserCertConflictException.java 0000664 0000000 0000000 00000000537 14565430767 0026711 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss;
public final class UserCertConflictException extends Exception {
private static final long serialVersionUID = 1L;
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/asn1/ 0000775 0000000 0000000 00000000000 14565430767 0021606 5 ustar 00root root 0000000 0000000 jss-5.5.0/base/src/main/java/org/mozilla/jss/asn1/ANY.java 0000664 0000000 0000000 00000022540 14565430767 0023103 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.asn1;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* Represents an ASN.1 ANY
value. An ANY is just an arbitrary
* ASN.1 value. It can be thought of as the simplest implementation of the
* ASN1Value
interface. Although they can be created
* from scratch (from raw BER), instances of ANY
are usually
* found after decoding
* with a template that has an ANY
field.
*
*
* An ANY
supports extracting the BER encoding, or decoding
* with a different template.
*/
public class ANY implements ASN1Value {
// The complete encoding of header + contents
private byte[] encoded;
private Tag tag;
/**
* Creates an ANY value, which is just a generic ASN.1 value.
* This method is provided for efficiency if the tag is already known,
* so that we don't have to parse the encoding for it.
*
* @param tag The tag of this value. It must be the same as the actual tag
* contained in the encoding.
* @param encoded The complete BER encoding of this value, including
* tag, form, length, and contents.
*/
public ANY(Tag tag, byte[] encoded) {
this.encoded = encoded;
this.tag = tag;
}
/**
* Creates an ANY value, which is just a generic ASN.1 value.
*
* @param encoded The complete BER encoding of this value, including
* tag, form, length, and contents.
* @throws InvalidBERException If there is an invalid BER encoding.
*/
public ANY(byte[] encoded) throws InvalidBERException {
try {
this.encoded = encoded;
ByteArrayInputStream bis = new ByteArrayInputStream(encoded);
ASN1Header head = new ASN1Header(bis);
this.tag = head.getTag();
} catch (IOException e) {
throw new org.mozilla.jss.util.AssertionException(
"IOException while creating ANY: " + e);
}
}
/**
* Returns the tag of this value.
*/
@Override
public Tag getTag() {
return tag;
}
/**
* Returns the complete encoding of header and contents, as passed into
* the constructor or read from a BER input stream.
*
* @return Encoded header and contents.
*/
public byte[] getEncoded() {
return encoded;
}
/**
* Returns the ASN.1 header from the encoding.
*
* @return ASN.1 header.
* @throws InvalidBERException If there is an invalid BER encoding.
* @throws IOException If other error occurred.
*/
public ASN1Header getHeader() throws InvalidBERException, IOException {
if (header == null) {
ByteArrayInputStream bis = new ByteArrayInputStream(encoded);
header = new ASN1Header(bis);
}
return header;
}
private ASN1Header header = null;
/**
* Strips out the header and returns just the contents octets of the
* encoding.
*/
private byte[] contents = null;
public byte[] getContents() throws InvalidBERException {
try {
if (contents == null) {
ByteArrayInputStream bis = new ByteArrayInputStream(encoded);
header = new ASN1Header(bis);
contents = new byte[bis.available()];
if ((contents.length != header.getContentLength()) &&
(header.getContentLength() != -1)) {
throw new InvalidBERException("Length of contents was not the " +
"same as the header predicted");
}
ASN1Util.readFully(contents, bis);
}
return contents;
} catch (IOException e) {
throw new RuntimeException("Unable to read byte array: " + e.getMessage(), e);
}
}
@Override
public void encode(OutputStream ostream) throws IOException {
ostream.write(encoded);
}
/**
* Decodes this ANY using the given template. This is useful if you
* originally decoded something as an ANY because you didn't know
* what it was, but now you know what it is supposed to be.
*
* @param template The template to use to decode this ANY.
* @return The output of the given template when it is fed the
* encoding of this ANY.
* @throws InvalidBERException If there is an invalid BER encoding.
*/
public ASN1Value decodeWith(ASN1Template template)
throws InvalidBERException {
try {
ByteArrayInputStream bis = new ByteArrayInputStream(encoded);
return template.decode(bis);
} catch (IOException e) {
throw new RuntimeException("Unable to read byte array: " + e.getMessage(), e);
}
}
/**
* Decodes this ANY using the given template. This is useful if you
* originally decoded something as an ANY because you didn't know
* what it was, but now you know what it is supposed to be.
*
* @param implicitTag The implicit tag for the encoding.
* @param template The template to use to decode this ANY.
* @return The output of the given template when it is fed the
* encoding of this ANY.
* @throws InvalidBERException If there is an invalid BER encoding.
* @throws IOException If other error occurred.
*/
public ASN1Value decodeWith(Tag implicitTag, ASN1Template template)
throws IOException, InvalidBERException {
ByteArrayInputStream bis = new ByteArrayInputStream(encoded);
return template.decode(implicitTag, bis);
}
/**
* @param implicitTag This parameter is ignored, because
* ANY values cannot have implicit tags.
* @throws IOException If an error occurred.
*/
@Override
public void encode(Tag implicitTag, OutputStream ostream)
throws IOException {
if (!implicitTag.equals(tag)) {
throw new RuntimeException("No implicit tags allowed for ANY");
}
ostream.write(encoded);
}
/**
* Extracts the contents from the ANY and encodes them with
* the provided tag.
*
* @param alternateTag Alternate tag.
* @param ostream Output stream.
* @throws InvalidBERException If there is an invalid BER encoding.
* @throws IOException If other error occurred.
*/
public void encodeWithAlternateTag(Tag alternateTag, OutputStream ostream)
throws IOException, InvalidBERException {
byte[] contents = getContents();
ASN1Header oldHead = getHeader();
assert (contents.length == oldHead.getContentLength());
ASN1Header newHead = new ASN1Header(alternateTag, oldHead.getForm(),
contents.length);
newHead.encode(ostream);
ostream.write(contents);
}
/**
* Returns a singleton instance of a decoding template.
*
* @return Decoding template.
*/
public static Template getTemplate() {
return templateInstance;
}
private static Template templateInstance = new Template();
/**
* A class for decoding ANY
values from BER.
*/
public static class Template implements ASN1Template {
@Override
public boolean tagMatch(Tag tag) {
return true; // wheeeeee...it's ANY!
}
@Override
public ASN1Value decode(InputStream istream)
throws IOException, InvalidBERException {
try {
ASN1Header head = ASN1Header.lookAhead(istream);
if (head.getContentLength() == -1) {
// indefinite length encoding
ByteArrayOutputStream recording = new ByteArrayOutputStream();
// eat the header off the input stream
head = new ASN1Header(istream);
// write the header to the recording stream
recording.write(head.encode());
// write all objects from the input stream to the recording
// stream, until we hit an END-OF-CONTENTS tag
ANY any;
ANY.Template anyt = new ANY.Template();
int count = 0;
do {
any = (ANY) anyt.decode(istream);
recording.write(any.getEncoded());
} while (!any.getTag().equals(Tag.EOC));
return new ANY(head.getTag(), recording.toByteArray());
}
// definite length encoding
byte[] data = new byte[(int) head.getTotalLength()];
ASN1Util.readFully(data, istream);
return new ANY(head.getTag(), data);
} catch (InvalidBERException e) {
throw new InvalidBERException(e, "ANY");
}
}
@Override
public ASN1Value decode(Tag implicitTag, InputStream istream)
throws IOException, InvalidBERException {
throw new InvalidBERException("Implicit tag on ANY");
}
} // End of Template
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/asn1/ASN1Header.java 0000664 0000000 0000000 00000030146 14565430767 0024270 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.asn1;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.util.ArrayList;
/**
* The portion of a BER encoding that precedes the contents octets. Consists
* of the tag, form, and length octets.
*/
public class ASN1Header {
// This is set by the the decoding constructor, and by the encode()
// method. If it is set by the decoding constructor, it is supposed
// to represent what was actually read from the input stream, so it
// must not be overwritten later by the output of encode(), which could
// be a different encoding (DER vs. BER, for example).
private byte[] cachedEncoding = null;
/**
* Returns the length of the header plus the length of the contents;
* the total length of the DER encoding of an ASN1 value. Returns
* -1 if indefinite length encoding was used.
*
* @return Total length.
*/
public long getTotalLength() {
return contentLength == -1 ? -1 : encode().length + contentLength;
}
private Tag tag;
public Tag getTag() {
return tag;
}
// -1 means indefinite length encoding
private long contentLength;
/**
* Returns -1 for indefinite length encoding.
*
* @return Content length.
*/
public long getContentLength() {
return contentLength;
}
// PRIMITIVE or CONSTRUCTED
public static final Form PRIMITIVE = Form.PRIMITIVE;
public static final Form CONSTRUCTED = Form.CONSTRUCTED;
private Form form;
/**
* Returns the Form, PRIMITIVE or CONSTRUCTED.
*
* @return The form.
*/
public Form getForm() {
return form;
}
// This is the maximum size of ASN1 Header we support.
// 32 bytes is pretty huge, I've never seen anything bigger than 7.
private static final int MAX_LOOK_AHEAD = 32;
/**
* Returns information about the next item in the stream, but does not
* consume any octets.
*
* @param derStream DER stream.
* @return ASN.1 header.
* @throws InvalidBERException If there is an invalid BER encoding.
* @exception IOException If the input stream does not support look ahead.
*/
public static ASN1Header lookAhead(InputStream derStream)
throws IOException, InvalidBERException {
if (!derStream.markSupported()) {
throw new IOException("Mark not supported on this input stream");
}
derStream.mark(MAX_LOOK_AHEAD);
ASN1Header info = new ASN1Header(derStream);
derStream.reset();
return info;
}
/**
* Gets info about the next item in the DER stream, consuming the
* identifier and length octets.
*
* @param istream Input stream.
* @throws InvalidBERException If there is an invalid BER encoding.
* @throws IOException If other error occurred.
*/
public ASN1Header(InputStream istream)
throws InvalidBERException, IOException {
// default BAOS size is 32 bytes, which is plenty
ByteArrayOutputStream encoding = new ByteArrayOutputStream();
int inInt = istream.read();
if (inInt == -1) {
throw new InvalidBERException("End-of-file reached while " +
"decoding ASN.1 header");
}
encoding.write(inInt);
byte byte1 = (byte) inInt;
Tag.Class tagClass;
//
// Get Tag Class
//
tagClass = Tag.Class.fromInt((byte1 & 0xff) >>> 6);
//
// Get form
//
if ((byte1 & 0x20) == 0x20) {
form = CONSTRUCTED;
} else {
form = PRIMITIVE;
}
//
// Get Tag Number
//
long tagNum;
if ((byte1 & 0x1f) == 0x1f) {
// long form
//
// read all octets into a Vector of Bytes
//
byte next;
ArrayList bV = new ArrayList<>();
// last byte has MSB == 0.
do {
inInt = istream.read();
if (inInt == -1) {
throw new InvalidBERException("End-of-file reached while"
+ " decoding ASN.1 header");
}
encoding.write(inInt);
next = (byte) inInt;
bV.add(Byte.valueOf(next));
} while ((next & 0x80) == 0x80);
assert (!bV.isEmpty());
//
// Copy Vector of 7-bit bytes into array of 8-bit bytes.
//
byte[] bA = new byte[((bV.size() * 7) + 7) / 8];
int v; // vector index
int a; // array index
// clear the target array
for (a = 0; a < bA.length; a++) {
bA[a] = 0;
}
int shift = 0; // the amount the Vector is shifted from the array
// copy bits from the Vector to the array, going from the
// end (LSB) to the beginning (MSB).
a = bA.length - 1;
for (v = bV.size() - 1; v >= 0; v--) {
assert (v >= 0);
assert (v < bV.size());
assert (a >= 0);
assert (a < bA.length);
// MSB is not part of the number
byte b = (byte) (bV.get(v).byteValue() & 0x7f);
bA[a] |= b << shift;
if (shift > 1) {
// The byte from the Vector falls across a byte boundary
// in the array. We've already got the less-significant
// bits, now copy the more-significant bits into
// the next element of the array.
assert (a > 0);
--a;
bA[a] |= b >>> (8 - shift);
}
shift = (shift + 7) % 8; // update shift
}
// Create a new unsigned BigInteger from the byte array
tagNum = (new BigInteger(1, bA)).longValue();
} else {
// short form
tagNum = byte1 & 0x1f;
}
tag = new Tag(tagClass, tagNum);
//
// Get Length
//
inInt = istream.read();
if (inInt == -1) {
throw new InvalidBERException("End-of-file reached while " +
"decoding ASN.1 header");
}
encoding.write(inInt);
byte lenByte = (byte) inInt;
if ((lenByte & 0x80) == 0) {
// short form
contentLength = lenByte;
} else {
// long form
if ((lenByte & 0x7f) == 0) {
// indefinite
contentLength = -1;
} else {
// definite
byte[] lenBytes = new byte[lenByte & 0x7f];
ASN1Util.readFully(lenBytes, istream);
encoding.write(lenBytes);
contentLength = (new BigInteger(1, lenBytes)).longValue();
}
}
// save our encoding so we don't have to recompute it later
cachedEncoding = encoding.toByteArray();
}
/**
* This constructor is to be called when we are constructing an ASN1Value
* rather than decoding it.
*
* @param tag Tag.
* @param form Form.
* @param contentLength Must be ≥0. Although indefinite length
* decoding is supported, indefinite length encoding
* is not.
*/
public ASN1Header(Tag tag, Form form, long contentLength) {
this.tag = tag;
this.form = form;
this.contentLength = contentLength;
}
public void encode(OutputStream ostream)
throws IOException {
ostream.write(encode());
}
public byte[] encode() {
// It's important that we not recompute the encoding if it was
// set by ASN1Header(InputStream), since in that case it represents
// the encoding that was actually read from the InputStream.
if (cachedEncoding != null) {
return cachedEncoding;
}
ByteArrayOutputStream cache = new ByteArrayOutputStream();
//
// Identifier octet(s)
//
byte idOctet = 0;
idOctet |= tag.getTagClass().toInt() << 6;
if (form == CONSTRUCTED) {
idOctet |= 0x20;
}
if (tag.getNum() <= 30) {
// short form
idOctet |= (tag.getNum() & 0x1f);
cache.write(idOctet);
} else {
// long form
idOctet |= 0x1f;
BigInteger tagNum = BigInteger.valueOf(tag.getNum());
cache.write(idOctet);
int bitlength = tagNum.bitLength();
int reps = (bitlength + 6) / 7;
for (reps = reps - 1; reps > 0; reps--) {
long shifted = tag.getNum() >>> (7 * reps);
cache.write((((byte) shifted) & 0x7f) | 0x80);
}
cache.write(((byte) tag.getNum()) & 0x7f);
}
//
// Length Octets
//
if (contentLength == -1) {
// indefinite form
cache.write((byte) 0x80);
} else if (contentLength <= 127) {
// short form
cache.write((byte) contentLength);
} else {
// long form
byte[] val = unsignedBigIntToByteArray(
BigInteger.valueOf(contentLength));
cache.write(((byte) val.length) | 0x80);
cache.write(val, 0, val.length);
}
cachedEncoding = cache.toByteArray();
return cachedEncoding;
}
/**
* Converts an unsigned BigInteger to a minimal-length byte array.
* This is necessary because BigInteger.toByteArray() attaches an extra
* sign bit, which could cause the size of the byte representation to
* be bumped up by an extra byte.
*
* @param bi Input BigInteger.
* @return Byte array.
*/
public static byte[] unsignedBigIntToByteArray(BigInteger bi) {
// find minimal number of bytes to hold this value
int bitlen = bi.bitLength(); // minimal number of bits, without sign
int bytelen;
if (bitlen == 0) {
// special case, since bitLength() returns 0
bytelen = 1;
} else {
bytelen = (bitlen + 7) / 8;
}
byte[] withSign = bi.toByteArray();
if (bytelen == withSign.length || bi.signum() < 0) {
return withSign;
}
// trim off extra byte at the beginning
assert (bytelen == withSign.length - 1);
assert (withSign[0] == 0);
byte[] without = new byte[bytelen];
System.arraycopy(withSign, 1, without, 0, bytelen);
return without;
}
/**
* Verifies that this header has the given tag and form.
*
* @param expectedTag Expected tag.
* @param expectedForm Expected form.
* @exception InvalidBERException If the header's tag or form
* differ from those passed in.
*/
public void validate(Tag expectedTag, Form expectedForm)
throws InvalidBERException {
validate(expectedTag);
if (getForm() != expectedForm) {
throw new InvalidBERException("Incorrect form: expected [" +
expectedForm + "], found [" + getForm());
}
}
/**
* Verifies that this head has the given tag.
*
* @param expectedTag Expected tag.
* @exception InvalidBERException If the header's tag differs from that
* passed in.
*/
public void validate(Tag expectedTag) throws InvalidBERException {
if (!getTag().equals(expectedTag)) {
throw new InvalidBERException("Incorrect tag: expected [" +
expectedTag + "], found [" + getTag() + "]");
}
}
/**
* @return true
if this is a BER end-of-contents marker.
*/
public boolean isEOC() {
return (tag.equals(Tag.EOC));
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/asn1/ASN1Template.java 0000664 0000000 0000000 00000004032 14565430767 0024646 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.asn1;
import java.io.IOException;
import java.io.InputStream;
/**
* An interface for decoding ASN1Values from their BER encodings.
*
* @see ASN1Value
*/
public interface ASN1Template {
/**
* Determines whether the given tag will satisfy this template.
*
* @param tag Tag.
* @return True if the given tag will satisfy this template.
*/
public boolean tagMatch(Tag tag);
/**
* Decodes an ASN1Value from the InputStream without an implicit tag.
*
* @param istream Must support marking (markSupported() == true).
* For example, ByteArrayInputStream and BufferedInputStream
* support marking, but FileInputStream does not. If your source
* does not support marking, you can wrap it in a
* BufferedInputStream.
* @return ASN.1 value.
* @throws InvalidBERException If there is an invalid BER encoding.
* @throws IOException If other error occurred.
*/
public ASN1Value decode(InputStream istream)
throws IOException, InvalidBERException;
/**
* Decodes an ASN1Value from the InputStream with the given implicit
* tag.
*
* @param implicitTag Implicit tag.
* @param istream Must support marking (markSupported() == true).
* For example, ByteArrayInputStream and BufferedInputStream
* support marking, but FileInputStream does not. If your source
* does not support marking, you can wrap it in a
* BufferedInputStream.
* @return ASN.1 value.
* @throws InvalidBERException If there is an invalid BER encoding.
* @throws IOException If other error occurred.
*/
public ASN1Value decode(Tag implicitTag, InputStream istream)
throws IOException, InvalidBERException;
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/asn1/ASN1Util.java 0000664 0000000 0000000 00000012102 14565430767 0024005 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.asn1;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.EOFException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
public class ASN1Util {
public static byte[] encode(ASN1Value val) {
return encode(val.getTag(), val);
}
public static byte[] encode(Tag implicitTag, ASN1Value val) {
try {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
val.encode(implicitTag, bos);
return bos.toByteArray();
} catch (IOException e) {
throw new RuntimeException("Unable to encode byte array: " + e.getMessage(), e);
}
}
public static ASN1Value decode(ASN1Template template, byte[] encoded)
throws InvalidBERException {
try {
ByteArrayInputStream bis = new ByteArrayInputStream(encoded);
return template.decode(bis);
} catch (IOException e) {
throw (InvalidBERException) new InvalidBERException("Unable to decode byte array: " + e.getMessage())
.initCause(e);
}
}
public static ASN1Value decode(Tag implicitTag, ASN1Template template,
byte[] encoded)
throws InvalidBERException {
try {
ByteArrayInputStream bis = new ByteArrayInputStream(encoded);
return template.decode(implicitTag, bis);
} catch (IOException e) {
throw (InvalidBERException) new InvalidBERException("Unable to decode byte array: " + e.getMessage())
.initCause(e);
}
}
/**
* Fills a byte array with bytes from an input stream. This method
* keeps reading until the array is filled, an IOException occurs, or EOF
* is reached. The byte array will be completely filled unless an
* exception is thrown.
*
* @param bytes A byte array which will be filled up.
* @param istream The input stream from which to read the bytes.
* @exception IOException If an IOException occurs reading from the
* stream, or EOF is reached before the byte array is filled.
*/
public static void readFully(byte[] bytes, InputStream istream)
throws IOException {
int numRead = 0;
while (numRead < bytes.length) {
int nr = istream.read(bytes, numRead, bytes.length - numRead);
if (nr == -1) {
throw new EOFException();
}
numRead += nr;
}
}
/**
* returns the ECC curve byte array given the X509 public key byte array
*
* @param X509PubKeyBytes byte array of an X509PubKey
* @param withHeader tells if the return byes should inclulde the tag and size header or not
* @return ECC curve byte array.
*/
public static byte[] getECCurveBytesByX509PublicKeyBytes(byte[] X509PubKeyBytes,
boolean withHeader)
throws IllegalArgumentException, ArrayIndexOutOfBoundsException,
NullPointerException {
if ((X509PubKeyBytes == null) || (X509PubKeyBytes.length == 0)) {
throw new IllegalArgumentException("X509PubKeyBytes null");
}
/* EC public key OID complete with tag and size */
byte[] EC_PubOIDBytes_full = ASN1Util.encode(OBJECT_IDENTIFIER.EC_PUBKEY_OID);
/* EC public key OID without tag and size */
byte[] EC_PubOIDBytes = Arrays.copyOfRange(EC_PubOIDBytes_full, 2, EC_PubOIDBytes_full.length);
int curveBeginIndex = 0;
for (int idx = 0; idx <= X509PubKeyBytes.length; idx++) {
byte[] tmp = Arrays.copyOfRange(X509PubKeyBytes, idx, idx + EC_PubOIDBytes.length);
if (Arrays.equals(tmp, EC_PubOIDBytes)) {
curveBeginIndex = idx + EC_PubOIDBytes.length;
break;
}
}
int curveByteArraySize = X509PubKeyBytes[curveBeginIndex + 1];
if (withHeader) {
/* actual curve with tag and size */
byte curve[] = Arrays.copyOfRange(X509PubKeyBytes, curveBeginIndex,
curveBeginIndex + curveByteArraySize + 2);
return curve;
}
/* actual curve without tag and size */
byte curve[] = Arrays.copyOfRange(X509PubKeyBytes, curveBeginIndex + 2,
curveBeginIndex + 2 + curveByteArraySize);
return curve;
}
/**
* getOIDdescription() returns a text description of the OID
* from OID byte array
* the OID byte array is expected to be without the OID Tag (6) and size
* (together 2 bytes)
*
* @param oidBA OID byte array.
* @return OID description.
*/
public static String getOIDdescription(byte[] oidBA) {
return getTagDescriptionByOid(oidBA);
}
/**
* get OID description JNI method
*/
private native static String getTagDescriptionByOid(byte[] oidBA);
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/asn1/ASN1Value.java 0000664 0000000 0000000 00000002263 14565430767 0024153 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.asn1;
import java.io.IOException;
import java.io.OutputStream;
/**
* A value that can be decoded from BER and encoded to DER.
*
* @see ASN1Template
*/
public interface ASN1Value {
/**
* Returns the base tag for this type, not counting any tags
* that may be imposed on it by its context.
*
* @return Base tag.
*/
public Tag getTag();
/**
* Write this value's DER encoding to an output stream using
* its own base tag.
*
* @param ostream Output stream.
* @throws IOException If an error occurred.
*/
public void encode(OutputStream ostream) throws IOException;
/**
* Write this value's DER encoding to an output stream using
* an implicit tag.
*
* @param implicitTag Implicit tag.
* @param ostream Output stream.
* @throws IOException If an error occurred.
*/
public void encode(Tag implicitTag, OutputStream ostream)
throws IOException;
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/asn1/BIT_STRING.java 0000664 0000000 0000000 00000024601 14565430767 0024160 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.asn1;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.BitSet;
/**
* An ASN.1 BIT STRING
, which is an ordered sequence of bits.
* The bits are stored the same way they are encoded in BER: as an array
* of bytes with 0-7 unused bits at the end.
*/
public class BIT_STRING implements ASN1Value {
private byte[] bits;
private int padCount;
private boolean removeTrailingZeroes = false;
/**
* @param bits The bits packed into an array of bytes, with padding
* at the end. The array may be empty (but not null), in which case
* padCount
must be zero. The array is referenced,
* not cloned.
* @param padCount The number of padding bits at the end of the array.
* Must be in the range [0,7]
.
* @exception NumberFormatException If padCount
is not in
* the range [0,7]
, or bits
is
* empty and padCount
is non-zero.
*/
public BIT_STRING(byte[] bits, int padCount)
throws NumberFormatException {
if (padCount < 0 || padCount > 7) {
throw new NumberFormatException();
}
if (bits.length == 0 && padCount != 0) {
throw new NumberFormatException();
}
this.bits = bits;
this.padCount = padCount;
}
/**
* Constructs a BIT_STRING from a BitSet.
*
* @param bs A BitSet.
* @param numBits The number of bits to copy from the BitSet.
* This is necessary because the size of a BitSet is always padded
* up to a multiple of 64, but not all of these bits may
* be significant.
* @exception NumberFormatException If numBits
is larger
* than bs.size()
or less than zero.
*/
public BIT_STRING(BitSet bs, int numBits)
throws NumberFormatException {
if (numBits < 0 || numBits > bs.size()) {
throw new NumberFormatException();
}
// allocate enough bytes to hold all the bits
bits = new byte[(numBits + 7) / 8];
padCount = (bits.length * 8) - numBits;
assert (padCount >= 0 && padCount <= 7);
for (int i = 0; i < numBits; i++) {
if (bs.get(i)) {
bits[i / 8] |= 0x80 >>> (i % 8);
}
}
}
/**
* Determines whether the DER-encoding of this bitstring will have
* its trailing zeroes removed. Generally, DER requires that trailing
* zeroes be removed when the bitstring is used to hold flags, but
* not when it is used to hold binary data (such as a public key).
* The default is false
.
*
* @return True if trailing zeroes are to be removed.
*/
public boolean getRemoveTrailingZeroes() {
return this.removeTrailingZeroes;
}
/**
* Determines whether the DER-encoding of this bitstring will have
* its trailing zeroes removed. Generally, DER requires that trailing
* zeroes be removed when the bitstring is used to hold flags, but
* not when it is used to hold binary data (such as a public key).
* The default is false
. If this bit string is used to hold
* flags, you should set this to true
.
*
* @param removeTrailingZeroes True if trailing zeroes are to be removed.
*/
public void setRemoveTrailingZeroes(boolean removeTrailingZeroes) {
this.removeTrailingZeroes = removeTrailingZeroes;
}
/**
* Returns the bits packed into an array of bytes, with padding
* at the end. The array may be empty (but not null), in which case
* padCount
must be zero. The array is referenced,
* not cloned.
*
* @return BIT STRING as byte array.
*/
public byte[] getBits() {
return bits;
}
/**
* Copies this BIT STRING into a Java BitSet. Note that BitSet.size()
* will not accurately reflect the number of bits in the BIT STRING,
* because the size of a BitSet is always rounded up to the next multiple
* of 64. The extra bits will be set to 0.
*
* @return BIT STRING as BitSet.
*/
public BitSet toBitSet() {
BitSet bs = new BitSet();
int numBits = (bits.length * 8) - padCount;
for (int i = 0; i < numBits; i++) {
if ((bits[i / 8] & (0x80 >>> (i % 8))) != 0) { //NOSONAR - int promotion bug is prevented by the applied mask
bs.set(i);
} else {
bs.clear(i);
}
}
return bs;
}
/**
* Copies this BIT STRING into a boolean array. Each element of the array
* represents one bit with true
for 1 and false
* for 0.
*
* @return BIT STRING as boolean array.
*/
public boolean[] toBooleanArray() {
boolean[] array = new boolean[(bits.length * 8) - padCount];
// all elements are set to false by default
for (int i = 0; i < array.length; i++) {
if ((bits[i / 8] & (0x80 >>> (i % 8))) != 0) { //NOSONAR - int promotion bug is prevented by the applied mask
array[i] = true;
}
}
return array;
}
/**
* Returns the number of padding bits at the end of the array.
* Must be in the range [0,7]
.
*
* @return Number of padding.
*/
public int getPadCount() {
return padCount;
}
public static final Tag TAG = new Tag(Tag.UNIVERSAL, 3);
public static final Form FORM = Form.PRIMITIVE;
@Override
public Tag getTag() {
return TAG;
}
@Override
public void encode(OutputStream ostream) throws IOException {
encode(TAG, ostream);
}
@Override
public void encode(Tag implicitTag, OutputStream ostream)
throws IOException {
// force all unused bits to be zero, in support of DER standard.
if (bits.length > 0) {
bits[bits.length - 1] &= (0xff << padCount);
}
int padBits;
int numBytes;
if (removeTrailingZeroes) {
// first pare off empty bytes
numBytes = bits.length;
for (; numBytes > 0; --numBytes) {
if (bits[numBytes - 1] != 0) {
break;
}
}
// Now compute the number of unused bits. This includes any
// trailing zeroes, whether they are significant or not.
if (numBytes == 0) {
padBits = 0;
} else {
for (padBits = 0; padBits < 8; ++padBits) {
if ((bits[numBytes - 1] & (1 << padBits)) != 0) { //NOSONAR - int promotion bug is prevented by the applied mask
break;
}
}
assert (padBits >= 0 && padBits <= 7);
}
} else {
// Don't remove trailing zeroes. Just write the bits out as-is.
padBits = padCount;
numBytes = bits.length;
}
ASN1Header head = new ASN1Header(implicitTag, FORM, numBytes + 1L);
head.encode(ostream);
ostream.write(padBits);
ostream.write(bits, 0, numBytes);
}
private static final Template templateInstance = new Template();
public static Template getTemplate() {
return templateInstance;
}
/**
* A class for decoding a BIT_STRING
from its BER encoding.
*/
public static class Template implements ASN1Template {
@Override
public boolean tagMatch(Tag tag) {
return (TAG.equals(tag));
}
@Override
public ASN1Value decode(InputStream istream)
throws IOException, InvalidBERException {
return decode(TAG, istream);
}
@Override
public ASN1Value decode(Tag implicitTag, InputStream istream)
throws IOException, InvalidBERException {
try {
ASN1Header head = new ASN1Header(istream);
head.validate(implicitTag);
if (head.getContentLength() == -1) {
// indefinite length encoding
ByteArrayOutputStream bos = new ByteArrayOutputStream();
int padCount = 0;
ASN1Header ahead;
do {
ahead = ASN1Header.lookAhead(istream);
if (!ahead.isEOC()) {
if (padCount != 0) {
throw new InvalidBERException("Element of constructed " +
"BIT STRING has nonzero unused bits, but is not\n" +
"the last element of the construction.");
}
BIT_STRING.Template bst = new BIT_STRING.Template();
BIT_STRING bs = (BIT_STRING) bst.decode(istream);
bos.write(bs.getBits());
padCount = bs.getPadCount();
}
} while (!ahead.isEOC());
// consume the EOC
ahead = new ASN1Header(istream);
return new BIT_STRING(bos.toByteArray(), padCount);
}
// First octet is the number of unused bits in last octet
int padCount = istream.read();
if (padCount == -1) {
throw new InvalidBERException.EOF();
} else if (padCount < 0 || padCount > 7) {
throw new InvalidBERException("Unused bits not in range [0,7]");
}
// get the rest of the octets
byte[] bits = new byte[(int) head.getContentLength() - 1];
ASN1Util.readFully(bits, istream);
return new BIT_STRING(bits, padCount);
} catch (InvalidBERException e) {
throw new InvalidBERException(e, "BIT STRING");
}
}
} // end of Template
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/asn1/BMPString.java 0000664 0000000 0000000 00000007355 14565430767 0024270 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.asn1;
import java.io.CharConversionException;
import java.io.UnsupportedEncodingException;
/**
* The ASN.1 type BMPString. BMPStrings use the Unicode character set.
* They are encoded and decoded in big-endian format using two octets.
*/
public class BMPString extends CharacterString {
/**
* Creates a new BMPString from an array of Java characters.
*
* @param chars Input characters.
* @throws CharConversionException If an error occurred.
*/
public BMPString(char[] chars) throws CharConversionException {
super(chars);
}
/**
* Creates a new BMPString from a Java String.
*
* @param s Input string.
* @throws CharConversionException If an error occurred.
*/
public BMPString(String s) throws CharConversionException {
super(s);
}
/**
* Returns the conversion object for converting between an encoded byte
* array an an array of Java characters.
*
* @return Character converter.
*/
@Override
CharConverter getCharConverter() {
return converterInstance;
}
private static final BMPConverter converterInstance = new BMPConverter();
static final Tag TAG = new Tag(Tag.UNIVERSAL, 30);
static final Form FORM = Form.PRIMITIVE;
@Override
public Tag getTag() {
return TAG;
}
/**
* Returns a singleton instance of BMPString.Template. This is more
* efficient than creating a new BMPString.Template.
*
* @return BMSString template.
*/
public static Template getTemplate() {
return templateInstance;
}
private static final Template templateInstance = new Template();
// nested class
public static class Template extends CharacterString.Template {
@Override
protected Tag getTag() {
return TAG;
}
@Override
public boolean tagMatch(Tag tag) {
return TAG.equals(tag);
}
@Override
protected CharConverter getCharConverter() {
return new BMPConverter();
}
@Override
protected CharacterString generateInstance(char[] chars)
throws CharConversionException {
return new BMPString(chars);
}
@Override
protected String typeName() {
return "BMPString";
}
}
private static class BMPConverter implements CharConverter {
@Override
public char[] byteToChar(byte[] bytes, int offset, int len)
throws CharConversionException {
try {
String s = new String(bytes, offset, len, "UnicodeBig");
return s.toCharArray();
} catch (UnsupportedEncodingException e) {
String err = "Unable to find UnicodeBig encoding mechanism";
throw (CharConversionException) new CharConversionException(err).initCause(e);
}
}
@Override
public byte[] charToByte(char[] chars, int offset, int len)
throws CharConversionException {
try {
// We don't want the byte-order mark
String s = new String(chars, offset, len);
return s.getBytes("UnicodeBigUnmarked");
} catch (UnsupportedEncodingException e) {
String err = "Unable to find UnicodeBigUnmarked encoding mechanism";
throw (CharConversionException) new CharConversionException(err).initCause(e);
}
}
} // end of char converter
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/asn1/BOOLEAN.java 0000664 0000000 0000000 00000005527 14565430767 0023541 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.asn1;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* An ASN.1 BOOLEAN
value.
*/
public class BOOLEAN implements ASN1Value {
public static final Tag TAG = new Tag(Tag.Class.UNIVERSAL, 1);
public static final Form FORM = Form.PRIMITIVE;
@Override
public Tag getTag() {
return TAG;
}
private ASN1Header getHeader(Tag implicitTag) {
return new ASN1Header(implicitTag, FORM, 1);
}
@Override
public void encode(OutputStream ostream) throws IOException {
encode(TAG, ostream);
}
@Override
public void encode(Tag implicitTag, OutputStream ostream)
throws IOException {
getHeader(implicitTag).encode(ostream);
if (val) {
ostream.write(0xff);
} else {
ostream.write(0x00);
}
}
private boolean val;
/**
* Creates a BOOLEAN
with the given value.
*
* @param val Boolean value.
*/
public BOOLEAN(boolean val) {
this.val = val;
}
/**
* @return The boolean value of this BOOLEAN
.
*/
public boolean toBoolean() {
return val;
}
/**
* Returns "true" or "false".
*/
@Override
public String toString() {
return val ? "true" : "false";
}
private static final Template templateInstance = new Template();
public static Template getTemplate() {
return templateInstance;
}
/**
* A Class for decoding BOOLEAN
values from their BER
* encodings.
*/
public static class Template implements ASN1Template {
@Override
public boolean tagMatch(Tag tag) {
return (tag.equals(BOOLEAN.TAG));
}
@Override
public ASN1Value decode(InputStream istream)
throws IOException, InvalidBERException {
return decode(TAG, istream);
}
@Override
public ASN1Value decode(Tag tag, InputStream istream)
throws IOException, InvalidBERException {
try {
ASN1Header head = new ASN1Header(istream);
head.validate(tag, FORM);
int b = istream.read();
if (b == -1) {
throw new InvalidBERException("End-of-file reached while " +
"decoding BOOLEAN");
}
return b == 0x00 ? new BOOLEAN(false) : new BOOLEAN(true);
} catch (InvalidBERException e) {
throw new InvalidBERException(e, "BOOLEAN");
}
}
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/asn1/CHOICE.java 0000664 0000000 0000000 00000020766 14565430767 0023416 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.asn1;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Vector;
/**
* Objects of this class are generated by CHOICE.Template.decode(). It is
* not necessary to use them to encode a CHOICE. Since the encoding of a
* CHOICE is simply the encoding of the chosen element, it is easier
* to just write out the chosen element.
*/
public class CHOICE implements ASN1Value {
private Tag tag;
private ASN1Value val;
/**
* Create a CHOICE whose chosen element has an implicit tag.
*
* @param implicitTag Implicit tag.
* @param val The value.
*/
public CHOICE(Tag implicitTag, ASN1Value val) {
tag = implicitTag;
this.val = val;
}
/**
* Create a CHOICE whose chosen element has no implicit tag.
*
* @param val The value.
*/
public CHOICE(ASN1Value val) {
this.tag = val.getTag();
this.val = val;
}
/**
* Returns the tag that the chosen element is encoded with, which is
* either the underlying tag of the element or an implicit tag.
*/
@Override
public Tag getTag() {
return tag;
}
/**
* @return The chosen value.
*/
public ASN1Value getValue() {
return val;
}
public static CHOICE.Template getTemplate() {
return new CHOICE.Template();
}
/**
* Encodes this CHOICE. This merely consists of encoding the chosen
* element with an implicit tag, if one was given in the constructor,
* or with its own underlying tag.
*/
@Override
public void encode(OutputStream ostream) throws IOException {
val.encode(tag, ostream);
}
/**
* Encodes this CHOICE. This merely consists of encoding the chosen
* element with an implicit tag, if one was given in the constructor,
* or with its own underlying tag.
*
* @param implicitTag This value is ignored. The tag of a CHOICE
* is merely the tag of the chosen element of the CHOICE. A
* CHOICE cannot itself have an implicit tag.
*/
@Override
public void encode(Tag implicitTag, OutputStream ostream)
throws IOException {
assert (implicitTag.equals(tag));
val.encode(tag, ostream);
}
/**
* A Template for decoding ASN.1 CHOICE
s
*/
public static class Template implements ASN1Template {
// The the various possibilities in this CHOICE
private Vector templates = new Vector<>();
/**
* Creates an empty CHOICE template
*/
public Template() {
}
/**
* Adds a new sub-template to this CHOICE template with no implicit tag.
*
* @param template Sub-template.
*/
public void addElement(ASN1Template template) {
templates.addElement(new Element(template));
}
/**
* Adds a new sub-template to this CHOICE template with an implicit tag.
*
* @param implicitTag Implicit tag.
* @param template Sub-template.
*/
public void addElement(Tag implicitTag, ASN1Template template) {
templates.addElement(new Element(implicitTag, template));
}
/**
* @return The number of elements in this CHOICE template.
*/
public int size() {
return templates.size();
}
/**
* @param index Element index.
* @return The element at the specified index.
*/
public ASN1Template elementAt(int index) {
return templates.elementAt(index).getTemplate();
}
/**
* Retrieves the implicit tag of the element at the specified index.
* Returns null if there is no implicit tag for this element.
*
* @param index Element index.
* @return The implicit tag.
*/
public Tag implicitTagAt(int index) {
return templates.elementAt(index).getImplicitTag();
}
/**
* Empties this CHOICE template.
*/
public void removeAllElements() {
templates.removeAllElements();
}
/**
* Removes the element at the specified index.
*
* @param index Element index.
*/
public void removeElementAt(int index) {
templates.removeElementAt(index);
}
/**
* Determines whether the given tag will satisfy this template.
*
* @param t The tag.
* @return True if the tag satisfies any sub-template.
*/
@Override
public boolean tagMatch(Tag t) {
int size = size();
for (int i = 0; i < size; i++) {
Tag impl = implicitTagAt(i);
if (impl != null) {
// There is an implicit tag, if we match it we have a match
if (impl.equals(t)) {
return true;
}
} else {
// no implicit tag, look at the sub-template itself
ASN1Template templ = elementAt(i);
if (templ.tagMatch(t)) {
return true;
}
}
}
// none of the elements matched
return false;
}
@Override
public ASN1Value decode(InputStream istream)
throws IOException, InvalidBERException {
ASN1Header head = ASN1Header.lookAhead(istream);
Tag tag = head.getTag();
// Loop over all the elements of the CHOICE template until we
// find one with a matching tag.
int size = size();
for (int i = 0; i < size; i++) {
if (implicitTagAt(i) != null) {
if (implicitTagAt(i).equals(tag)) {
// match by implicit tag!
ASN1Value val = elementAt(i).decode(implicitTagAt(i),
istream);
//return elementAt(i).decode( implicitTagAt(i), istream );
return new CHOICE(implicitTagAt(i), val);
}
} else {
if (elementAt(i).tagMatch(tag)) {
// match by base tag !
//return elementAt(i).decode(istream);
return new CHOICE(elementAt(i).decode(istream));
}
}
}
// we didn't find any match
throw new InvalidBERException("Unable to decode CHOICE");
}
// Implicit tags are illegal for CHOICE (and ANY)
/**
* Decodes a CHOICE.
*
* @param implicitTag This parameter is ignored. A choice
* cannot have an implicit tag.
*/
@Override
public ASN1Value decode(Tag implicitTag, InputStream istream)
throws IOException, InvalidBERException {
return decode(istream);
}
/**
* An element in a CHOICE template, consisting of a nested template
* and, optionally, an implicit tag for that template.
*/
private static class Element {
private ASN1Template template;
private Tag implicitTag = null;
/**
* Creates a CHOICE template element with no implicit tag.
*/
public Element(ASN1Template template) {
this.template = template;
}
/**
* Creates a CHOICE template element with an implicit tag.
*/
public Element(Tag implicitTag, ASN1Template template) {
this.template = template;
this.implicitTag = implicitTag;
}
/**
* Returns the template of this CHOICE template element.
*/
public ASN1Template getTemplate() {
return template;
}
/**
* Returns the implicit tag for this CHOICE template element,
* if there is one. If not, returns null.
*/
public Tag getImplicitTag() {
return implicitTag;
}
}
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/asn1/CharConverter.java 0000664 0000000 0000000 00000001014 14565430767 0025212 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.asn1;
import java.io.CharConversionException;
interface CharConverter {
public char[] byteToChar(byte[] bytes, int offset, int len)
throws CharConversionException;
public byte[] charToByte(char[] chars, int offset, int len)
throws CharConversionException;
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/asn1/CharacterString.java 0000664 0000000 0000000 00000012314 14565430767 0025535 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.asn1;
import java.io.ByteArrayOutputStream;
import java.io.CharConversionException;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* An abstract base class for all character string types in ASN.1.
*/
public abstract class CharacterString implements ASN1Value {
abstract CharConverter getCharConverter();
@Override
public abstract Tag getTag();
static final Form FORM = Form.PRIMITIVE;
private char[] chars;
/**
* Converts this ASN.1 character string to a Java String.
*
* @return ASN.1 character string as String.
*/
@Override
public String toString() {
return new String(chars);
}
/**
* Converts this ASN.1 character string to an array of Java characters.
*
* @return ASN.1 character string as character array.
*/
public char[] toCharArray() {
return chars;
}
protected CharacterString(char[] chars) throws CharConversionException {
this.chars = chars;
cachedContents = computeContents();
}
protected CharacterString(String s) throws CharConversionException {
this.chars = s.toCharArray();
cachedContents = computeContents();
}
private byte[] cachedContents;
private byte[] getEncodedContents() {
return cachedContents;
}
private byte[] computeContents() throws CharConversionException {
CharConverter converter = getCharConverter();
byte[] contents = converter.charToByte(chars, 0, chars.length);
return contents;
}
@Override
public void encode(OutputStream ostream) throws IOException {
encode(getTag(), ostream);
}
@Override
public void encode(Tag implicitTag, OutputStream ostream)
throws IOException {
byte[] contents = getEncodedContents();
ASN1Header head = new ASN1Header(implicitTag, FORM, contents.length);
head.encode(ostream);
ostream.write(contents);
}
public abstract static class Template implements ASN1Template {
/**
* Must be overridden to return the tag for the subclass.
*
* @return Tag.
*/
protected abstract Tag getTag();
@Override
public abstract boolean tagMatch(Tag tag);
/**
* Must be overridden to return the correct character converter
* for the subclass.
*
* @return Character converter.
*/
protected abstract CharConverter getCharConverter();
/**
* Must be overridden to create an instance of the subclass given
* a char array.
*
* @param chars Input characters.
* @return Character string.
* @throws CharConversionException If an error occurred.
*/
protected abstract CharacterString generateInstance(char[] chars)
throws CharConversionException;
/**
* Must be overridden to provide the name of the subclass, for including
* into error messages.
*
* @return Name of the subclass.
*/
protected abstract String typeName();
@Override
public ASN1Value decode(InputStream istream)
throws IOException, InvalidBERException {
return decode(getTag(), istream);
}
@Override
public ASN1Value decode(Tag implicitTag, InputStream istream)
throws IOException, InvalidBERException {
try {
ASN1Header head = new ASN1Header(istream);
head.validate(implicitTag);
byte[] raw; // raw bytes, not translated to chars yet
if (head.getContentLength() == -1) {
// indefinite length encoding
ASN1Header ahead;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
do {
ahead = ASN1Header.lookAhead(istream);
if (!ahead.isEOC()) {
OCTET_STRING.Template ot = new OCTET_STRING.Template();
OCTET_STRING os = (OCTET_STRING) ot.decode(istream);
bos.write(os.toByteArray());
}
} while (!ahead.isEOC());
// consume EOC
ahead = new ASN1Header(istream);
raw = bos.toByteArray();
} else {
// definite length
raw = new byte[(int) head.getContentLength()];
ASN1Util.readFully(raw, istream);
}
char[] chars = getCharConverter().byteToChar(raw, 0, raw.length);
return generateInstance(chars);
} catch (CharConversionException e) {
throw new InvalidBERException(e.getMessage());
} catch (InvalidBERException e) {
throw new InvalidBERException(e, typeName());
}
}
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/asn1/CountingStream.java 0000664 0000000 0000000 00000005454 14565430767 0025423 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.asn1;
import java.io.IOException;
import java.io.InputStream;
/**
* This class keeps track of the number of bytes that have been read from
* a stream. It will be incremented by the number of bytes read or skipped.
* If the stream is marked and then reset, the number of bytes read will
* be reset as well.
*/
class CountingStream extends InputStream {
private int count = 0;
private int markpos;
private InputStream source;
private static final boolean DEBUG = false;
public CountingStream(InputStream source) {
this.source = source;
}
@Override
public int available() throws IOException {
return source.available();
}
@Override
public synchronized void mark(int readlimit) {
source.mark(readlimit);
markpos = count;
if (DEBUG) {
System.out.println("Marked at position " + markpos);
}
}
@Override
public boolean markSupported() {
return source.markSupported();
}
@Override
public int read() throws IOException {
int n = source.read();
if (n != -1) {
count++;
if (DEBUG) {
System.out.println("read() 1 byte, count=" + count);
}
}
return n;
}
@Override
public int read(byte[] buffer) throws IOException {
int n = source.read(buffer);
if (n != -1) {
count += n;
}
if (DEBUG) {
System.out.println("read([]) " + n + " bytes, count=" + count);
}
return n;
}
@Override
public int read(byte[] buffer, int offset, int count) throws IOException {
int n = source.read(buffer, offset, count);
if (n != -1) {
this.count += n;
}
if (DEBUG) {
System.out.println("read(...) " + n + " bytes, count=" + this.count);
}
return n;
}
@Override
public synchronized void reset() throws IOException {
source.reset();
if (DEBUG) {
System.out.println("reset from " + count + " to " + markpos);
}
count = markpos;
}
@Override
public long skip(long count) throws IOException {
this.count += count;
if (DEBUG) {
System.out.println("skipped " + count + ", now at " + this.count);
}
return source.skip(count);
}
public int getNumRead() {
return count;
}
public void resetNumRead() {
count = 0;
markpos = 0;
if (DEBUG) {
System.out.println("resetting count to 0");
}
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/asn1/ENUMERATED.java 0000664 0000000 0000000 00000004665 14565430767 0024115 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.asn1;
import java.io.IOException;
import java.io.InputStream;
/**
* Represents an ASN.1 ENUMERATED
value. This has the same
* interface as INTEGER
*/
public class ENUMERATED extends INTEGER {
private static final long serialVersionUID = 1L;
public static final Tag TAG = new Tag(Tag.Class.UNIVERSAL, 10);
@Override
public Tag getTag() {
return TAG;
}
/**
* Creates a new ENUMERATED value from a long int.
*
* @param val Input value.
*/
public ENUMERATED(long val) {
super(val);
}
ENUMERATED(byte[] valBytes) {
super(valBytes);
}
/**
* @return The value as a long int.
*/
public long getValue() {
return longValue();
}
private static final ENUMERATED.Template templateInstance = new ENUMERATED.Template();
public static ASN1Template getTemplate() {
return templateInstance;
}
/**
* A template for decoding ENUMERATED values from their BER encodings.
* The template reads the value as an INTEGER. It does not check that it
* is a valid value for the ENUMERATED type.
*/
public static class Template
extends INTEGER.Template {
@Override
Tag getTag() {
return ENUMERATED.TAG;
}
@Override
public boolean tagMatch(Tag tag) {
return (tag.equals(ENUMERATED.TAG));
}
@Override
public ASN1Value decode(Tag tag, InputStream derStream)
throws InvalidBERException, IOException {
try {
ASN1Header wrapper = new ASN1Header(derStream);
wrapper.validate(tag, FORM);
// Is length < 1 ?
if (wrapper.getContentLength() < 1) {
throw new InvalidBERException("Invalid 0 length for ENUMERATED");
}
byte[] valBytes = new byte[(int) wrapper.getContentLength()];
ASN1Util.readFully(valBytes, derStream);
return new ENUMERATED(valBytes);
} catch (InvalidBERException e) {
throw new InvalidBERException(e, "ENUMERATED");
}
}
} // end of Template
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/asn1/EXPLICIT.java 0000664 0000000 0000000 00000010323 14565430767 0023671 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.asn1;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
/**
* An explicit tag.
*/
public class EXPLICIT implements ASN1Value {
public static final Form FORM = Form.CONSTRUCTED;
private ASN1Value content;
private Tag tag;
/**
* Creates an EXPLICIT tag wrapping some other ASN1Value. For example,
* for the following ASN.1 snippet:
*
*
* MyType [3] EXPLICIT INTEGER
*
*
* assuming a sample value of 5 for the INTEGER, a MyType could be
* created with:
*
*
* EXPLICIT myValue = new EXPLICIT(new Tag(3), new INTEGER(5));
*
*
* @param tag Tag.
* @param content Content.
*/
public EXPLICIT(Tag tag, ASN1Value content) {
assert (tag != null && content != null);
this.content = content;
this.tag = tag;
}
/**
* @return the ASN1Value that is wrapped by this EXPLICIT tag.
*/
public ASN1Value getContent() {
return content;
}
/**
* Returns the Tag of this EXPLICIT tag.
*/
@Override
public Tag getTag() {
return tag;
}
@Override
public void encode(OutputStream ostream) throws IOException {
encode(tag, ostream);
}
@Override
public void encode(Tag implicitTag, OutputStream ostream)
throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
content.encode(bos);
byte[] contentBytes = bos.toByteArray();
ASN1Header head = new ASN1Header(implicitTag, FORM,
contentBytes.length);
head.encode(ostream);
ostream.write(contentBytes);
}
public static Template getTemplate(Tag tag, ASN1Template content) {
return new Template(tag, content);
}
/**
* A template for decoding an object wrapped in an EXPLICIT tag.
*/
public static class Template implements ASN1Template {
private ASN1Template content;
private Tag tag;
/**
* Creates a template for unwrapping an object wrapped in an explicit tag.
* For example, to decode:
*
*
* MyValue ::= [3] EXPLICIT INTEGER
*
*
* use:
*
*
* EXPLICIT.Template myTemplate = new EXPLICIT.Template(new Tag(3),
* new INTEGER.Template());
*
*
* @param tag The tag value of the EXPLICIT tag.
* @param content The template for decoding the object that is wrapped
* in the explicit tag.
*/
public Template(Tag tag, ASN1Template content) {
this.content = content;
this.tag = tag;
}
@Override
public boolean tagMatch(Tag tag) {
return (this.tag.equals(tag));
}
@Override
public ASN1Value decode(InputStream istream)
throws IOException, InvalidBERException {
return decode(tag, istream);
}
@Override
public ASN1Value decode(Tag implicitTag, InputStream istream)
throws IOException, InvalidBERException {
try {
ASN1Header head = new ASN1Header(istream);
head.validate(implicitTag, Form.CONSTRUCTED);
ASN1Value val = content.decode(istream);
EXPLICIT e = new EXPLICIT(tag, val);
// if indefinite content length, consume the end-of-content marker
if (head.getContentLength() == -1) {
head = new ASN1Header(istream);
if (!head.isEOC()) {
throw new InvalidBERException("No end-of-contents marker");
}
}
return e;
} catch (InvalidBERException e) {
throw new InvalidBERException(e, "EXPLICIT");
}
}
} // end of Template
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/asn1/FieldNotPresentException.java 0000664 0000000 0000000 00000001565 14565430767 0027404 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.asn1;
/**
* An exception thrown when an optional field is not present.
*/
public class FieldNotPresentException extends java.lang.Exception {
private static final long serialVersionUID = 1L;
public FieldNotPresentException() {
super();
}
public FieldNotPresentException(String mesg) {
super(mesg);
}
public FieldNotPresentException(String mesg, Throwable cause) {
super(mesg, cause);
}
public FieldNotPresentException(String mesg, Throwable cause, boolean enableSuppression,
boolean writableStackTrace) {
super(mesg, cause, enableSuppression, writableStackTrace);
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/asn1/Form.java 0000664 0000000 0000000 00000001302 14565430767 0023350 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.asn1;
/**
* An enumerated type representing the forms of an ASN.1 value.
* The possibilities are PRIMITIVE and CONSTRUCTED.
*/
public class Form {
private String name;
private Form() {
}
private Form(String name) {
this.name = name;
}
public static final Form PRIMITIVE = new Form("PRIMITIVE");
public static final Form CONSTRUCTED = new Form("CONSTRUCTED");
@Override
public String toString() {
return name;
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/asn1/GeneralizedTime.java 0000664 0000000 0000000 00000003013 14565430767 0025516 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.asn1;
import java.util.Date;
/**
* The ASN.1 type GeneralizedTime
*/
public class GeneralizedTime extends TimeBase {
public static final Tag TAG = new Tag(Tag.UNIVERSAL, 24);
@Override
public Tag getTag() {
return TAG;
}
/**
* Creates a GeneralizedTime
from a Date.
*
* @param date Input date.
*/
public GeneralizedTime(Date date) {
super(date);
}
@Override
protected boolean isUTC() {
return false;
}
private static final GeneralizedTime.Template templateInstance = new GeneralizedTime.Template();
public static GeneralizedTime.Template getTemplate() {
return templateInstance;
}
/**
* A class for decoding GeneralizedTime
s.
*/
public static class Template extends TimeBase.Template
implements ASN1Template {
@Override
protected Tag getTag() {
return TAG;
}
@Override
public boolean tagMatch(Tag tag) {
return TAG.equals(tag);
}
@Override
protected boolean isUTC() {
return false;
}
@Override
protected TimeBase generateInstance(Date date) {
return new GeneralizedTime(date);
}
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/asn1/IA5String.java 0000664 0000000 0000000 00000005516 14565430767 0024225 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.asn1;
import java.io.CharConversionException;
public class IA5String extends CharacterString {
public IA5String(char[] chars) throws CharConversionException {
super(chars);
}
public IA5String(String s) throws CharConversionException {
super(s);
}
@Override
CharConverter getCharConverter() {
return new IA5Converter();
}
public static final Tag TAG = new Tag(Tag.Class.UNIVERSAL, 22);
@Override
public Tag getTag() {
return TAG;
}
public static Template getTemplate() {
return templateInstance;
}
private static final Template templateInstance = new Template();
// nested class
public static class Template
extends CharacterString.Template {
@Override
public Tag getTag() {
return IA5String.TAG;
}
@Override
public boolean tagMatch(Tag tag) {
return (tag.equals(IA5String.TAG));
}
@Override
protected CharConverter getCharConverter() {
return new IA5Converter();
}
@Override
protected CharacterString generateInstance(char[] chars)
throws CharConversionException {
return new IA5String(chars);
}
@Override
protected String typeName() {
return "IA5String";
}
}
// nested class
private static class IA5Converter implements CharConverter {
@Override
public char[] byteToChar(byte[] bytes, int offset, int len)
throws CharConversionException {
char[] chars = new char[len];
int c; // char index
int b; // byte index
for (b = offset, c = 0; c < len; b++, c++) {
if ((bytes[b] & 0x80) != 0) {
throw new CharConversionException("Invalid character: " +
bytes[b]);
}
chars[c] = (char) (bytes[b] & 0x7f);
}
return chars;
}
@Override
public byte[] charToByte(char[] chars, int offset, int len)
throws CharConversionException {
byte[] bytes = new byte[len];
int c; // char index
int b; // byte index
for (c = offset, b = 0; b < len; c++, b++) {
if ((chars[c] & 0x7f) != chars[c]) {
throw new CharConversionException("Invalid character: " +
chars[c]);
}
bytes[b] = (byte) (chars[c] & 0x7f);
}
return bytes;
}
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/asn1/INTEGER.java 0000664 0000000 0000000 00000014647 14565430767 0023562 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.asn1;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.util.Random;
/**
* The ASN.1 type INTEGER
. This class extends BigInteger.
*/
public class INTEGER extends BigInteger implements ASN1Value {
private static final long serialVersionUID = 1L;
private byte[] encodedContents = null;
private byte[] getEncodedContents() {
if (encodedContents == null) {
encodedContents = toByteArray();
}
return encodedContents;
}
private ASN1Header getHeader(Tag t) {
return new ASN1Header(t, FORM, getContentLength());
}
public INTEGER(String s) throws NumberFormatException {
super(s);
}
public INTEGER(String s, int r) throws NumberFormatException {
super(s, r);
}
public INTEGER(byte[] bval) throws NumberFormatException {
super(bval);
}
public INTEGER(int sign, byte[] mag) throws NumberFormatException {
super(sign, mag);
}
public INTEGER(int numBits, Random rnd) throws NumberFormatException {
super(numBits, rnd);
}
public INTEGER(int bitLength, int certainty, Random rnd) {
super(bitLength, certainty, rnd);
}
public INTEGER(long val) {
super(BigInteger.valueOf(val).toByteArray());
}
public INTEGER(BigInteger bi) {
super(bi.toByteArray());
}
public static final Tag TAG = new Tag(Tag.Class.UNIVERSAL, 2);
@Override
public Tag getTag() {
return TAG;
}
public static final Form FORM = Form.PRIMITIVE;
@Override
public void encode(OutputStream outStream) throws IOException {
encode(getTag(), outStream);
}
@Override
public void encode(Tag implicitTag, OutputStream outStream)
throws IOException {
// write header
getHeader(implicitTag).encode(outStream);
// write contents
outStream.write(getEncodedContents());
}
public long getContentLength() {
return getEncodedContents().length;
}
public byte[] encode() throws IOException {
ByteArrayOutputStream b = new ByteArrayOutputStream();
encode(b);
return b.toByteArray();
}
private static final INTEGER.Template templateInstance = new INTEGER.Template();
public static ASN1Template getTemplate() {
return templateInstance;
}
/**
* Tests the DER encoding and decoding of the INTEGER class.
*
* @param args Arguments.
*/
public static void main(String args[]) {
try {
int[] Is = new int[11];
int[][] Bs = new int[11][];
int i = 0;
Is[i] = 0;
Bs[i++] = new int[] { 0x02, 0x01, 0x00 };
Is[i] = 1;
Bs[i++] = new int[] { 0x02, 0x01, 0x01 };
Is[i] = -1;
Bs[i++] = new int[] { 0x02, 0x01, 0xff };
Is[i] = 127;
Bs[i++] = new int[] { 0x02, 0x01, 0x7f };
Is[i] = 128;
Bs[i++] = new int[] { 0x02, 0x02, 0x00, 0x80 };
Is[i] = 255;
Bs[i++] = new int[] { 0x02, 0x02, 0x00, 0xff };
Is[i] = 256;
Bs[i++] = new int[] { 0x02, 0x02, 0x01, 0x00 };
Is[i] = -128;
Bs[i++] = new int[] { 0x02, 0x01, 0x80 };
Is[i] = -129;
Bs[i++] = new int[] { 0x02, 0x02, 0xff, 0x7f };
Is[i] = 43568;
Bs[i++] = new int[] { 0x02, 0x03, 0x00, 0xaa, 0x30 };
Is[i] = -43568;
Bs[i++] = new int[] { 0x02, 0x03, 0xff, 0x55, 0xd0 };
for (i = 0; i < Is.length; i++) {
INTEGER I = new INTEGER(Is[i]);
byte[] compare = I.encode();
if (!arraysEqual(compare, Bs[i])) {
System.err.println("Encoding FAILED: " + Is[i]);
System.exit(-1);
}
ByteArrayInputStream bis = new ByteArrayInputStream(compare);
Template template = new Template();
INTEGER create = (INTEGER) template.decode(bis);
if (create.intValue() != Is[i]) {
System.err.println("Decoding FAILED: " + Is[i]);
System.exit(-1);
}
}
System.out.println("PASS");
} catch (Exception e) {
e.printStackTrace();
}
}
private static boolean arraysEqual(byte[] bytes, int[] ints) {
if (bytes == null || ints == null) {
return false;
}
if (bytes.length != ints.length) {
return false;
}
for (int i = 0; i < bytes.length; i++) {
if (bytes[i] != (byte) ints[i]) {
return false;
}
}
return true;
}
///////////////////////////////////////////////////////////////////////
// INTEGER.Template
// This is a nested class.
//
public static class Template implements ASN1Template {
Tag getTag() {
return INTEGER.TAG;
}
@Override
public boolean tagMatch(Tag tag) {
return (tag.equals(INTEGER.TAG));
}
@Override
public ASN1Value decode(InputStream derStream)
throws InvalidBERException, IOException {
return decode(getTag(), derStream);
}
@Override
public ASN1Value decode(Tag tag, InputStream derStream)
throws InvalidBERException, IOException {
try {
ASN1Header wrapper = new ASN1Header(derStream);
wrapper.validate(tag, FORM);
// Is length < 1 ?
if (wrapper.getContentLength() < 1) {
throw new InvalidBERException("Invalid 0 length for INTEGER");
}
byte[] valBytes = new byte[(int) wrapper.getContentLength()];
ASN1Util.readFully(valBytes, derStream);
return new INTEGER(valBytes);
} catch (InvalidBERException e) {
throw new InvalidBERException(e, "INTEGER");
}
}
} // end of class Template
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/asn1/InvalidBERException.java 0000664 0000000 0000000 00000004420 14565430767 0026247 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.asn1;
import java.util.Vector;
/**
* An exception thrown when BER decoding fails.
*/
public class InvalidBERException extends java.lang.Exception {
private static final long serialVersionUID = 1L;
private InvalidBERException child = null;
private Vector mesgList = new Vector<>();
public InvalidBERException(String mesg) {
super(mesg);
}
public void append(String mesg) {
mesgList.addElement(mesg);
}
public InvalidBERException(InvalidBERException e, String mesg) {
super(mesg);
child = e;
}
/**
* Prints out the exception class and error message, including
* all the nested exceptions.
*/
private void appendMessages(StringBuffer sb) {
int numMessages = mesgList.size();
for (int i = numMessages - 1; i >= 0; --i) {
sb.append(mesgList.elementAt(i));
sb.append(" >> ");
}
sb.append(getMessage());
}
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
sb.append(this.getClass().getName());
sb.append(": ");
appendMessages(sb);
return sb.toString();
}
public String toStringNested() {
StringBuffer sb = new StringBuffer();
appendMessages(sb);
if (child != null) {
sb.append(" >> ");
sb.append(child.toStringNested());
}
return sb.toString();
}
public static class EOF extends InvalidBERException {
private static final long serialVersionUID = 1L;
public EOF() {
super("Unexpected end-of-file encountered");
}
}
public static class InvalidChar extends InvalidBERException {
private static final long serialVersionUID = 1L;
public InvalidChar(byte b, int offset) {
super("Invalid character (" + b + ") encountered at offset " + offset);
}
public InvalidChar(char c, int offset) {
super("Invalid character (" + c + ") encountered at offset" + offset);
}
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/asn1/NULL.java 0000664 0000000 0000000 00000004356 14565430767 0023233 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.asn1;
import java.io.OutputStream;
import java.io.InputStream;
import java.io.IOException;
public class NULL implements ASN1Value {
public static final Tag TAG = new Tag(Tag.Class.UNIVERSAL, 5);
@Override
public Tag getTag() {
return TAG;
}
public static final Form FORM = Form.PRIMITIVE;
@Override
public void encode(OutputStream ostream) throws IOException {
encode(TAG, ostream);
}
@Override
public void encode(Tag implicitTag, OutputStream ostream)
throws IOException {
ASN1Header head = new ASN1Header(implicitTag, FORM, 0);
head.encode(ostream);
}
private static final NULL instance = new NULL();
public static NULL getInstance() {
return instance;
}
private static final Template templateInstance = new Template();
public static Template getTemplate() {
return templateInstance;
}
public static class Template implements ASN1Template {
public Tag getTag() {
return NULL.TAG;
}
@Override
public boolean tagMatch(Tag tag) {
return (tag.equals(NULL.TAG));
}
@Override
public ASN1Value decode(InputStream istream)
throws IOException, InvalidBERException {
return decode(getTag(), istream);
}
@Override
public ASN1Value decode(Tag implicitTag, InputStream istream)
throws IOException, InvalidBERException {
try {
ASN1Header head = new ASN1Header(istream);
head.validate(implicitTag, FORM);
if (head.getContentLength() != 0) {
throw new InvalidBERException("Invalid length (" +
head.getContentLength() + ") for NULL; only 0 is permitted");
}
return new NULL();
} catch (InvalidBERException e) {
throw new InvalidBERException(e, "NULL");
}
}
} // end of Template
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/asn1/OBJECT_IDENTIFIER.java 0000664 0000000 0000000 00000044456 14565430767 0025136 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.asn1;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.StringTokenizer;
import java.util.Vector;
public class OBJECT_IDENTIFIER implements ASN1Value {
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
// Standard object identifiers
///////////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////////
/**
* The OID space for EC
*/
public static final OBJECT_IDENTIFIER EC_PUBKEY_OID = new OBJECT_IDENTIFIER(new long[] { 1, 2, 840, 10045, 2, 1 });
/**
* The OID space for RSA Data Security, Inc.
*/
public static final OBJECT_IDENTIFIER RSADSI = new OBJECT_IDENTIFIER(new long[] { 1, 2, 840, 113549 });
/**
* The OID space for RSA's PKCS (public key cryptography standards).
*/
public static final OBJECT_IDENTIFIER PKCS = RSADSI.subBranch(1);
/**
* The OID space for RSA's PKCS #1.
*/
public static final OBJECT_IDENTIFIER PKCS1 = PKCS.subBranch(1);
/**
* The OID space for RSA's PKCS #2, which has since been folded into
* PKCS #1.
*/
public static final OBJECT_IDENTIFIER PKCS2 = PKCS.subBranch(2);
/**
* The OID space for RSA's message digest algorithms.
*/
public static final OBJECT_IDENTIFIER RSA_DIGEST = RSADSI.subBranch(2);
/**
* The OID space for RSA's password-based encryption standard.
*/
public static final OBJECT_IDENTIFIER PKCS5 = PKCS.subBranch(5);
/**
* The OID space for RSA's Selected Attribute Types standard, PKCS #9.
*/
public static final OBJECT_IDENTIFIER PKCS9 = PKCS.subBranch(9);
/**
* The OID space for RSA's personal information exchange syntax standard.
*/
public static final OBJECT_IDENTIFIER PKCS12 = PKCS.subBranch(12);
/**
* The OID space for RSA's ciphers.
*/
public static final OBJECT_IDENTIFIER RSA_CIPHER = RSADSI.subBranch(3);
/**
* The OID space for FIPS standardized algorithms.
*/
public static final OBJECT_IDENTIFIER ALGORITHM = new OBJECT_IDENTIFIER(new long[] { 1, 3, 14, 3, 2 });
/**
* The OID space for FIPS-180-2 SHA256/SHA384/SHA512 standardized algorithms.
*/
public static final OBJECT_IDENTIFIER HASH_ALGORITHM = new OBJECT_IDENTIFIER(
new long[] { 2, 16, 840, 1, 101, 3, 4, 2 });
/**
* The OID space for PKIX.
*/
public static final OBJECT_IDENTIFIER PKIX = new OBJECT_IDENTIFIER(new long[] { 1, 3, 6, 1, 5, 5, 7 });
public static final OBJECT_IDENTIFIER id_cmc = PKIX.subBranch(7);
/**
* CMC control attributes
*/
public static final OBJECT_IDENTIFIER id_cmc_cMCStatusInfo = id_cmc.subBranch(1);
public static final OBJECT_IDENTIFIER id_cmc_identification = id_cmc.subBranch(2);
public static final OBJECT_IDENTIFIER id_cmc_identityProof = id_cmc.subBranch(3);
public static final OBJECT_IDENTIFIER id_cmc_dataReturn = id_cmc.subBranch(4);
public static final OBJECT_IDENTIFIER id_cmc_transactionId = id_cmc.subBranch(5);
public static final OBJECT_IDENTIFIER id_cmc_senderNonce = id_cmc.subBranch(6);
public static final OBJECT_IDENTIFIER id_cmc_recipientNonce = id_cmc.subBranch(7);
public static final OBJECT_IDENTIFIER id_cmc_addExtensions = id_cmc.subBranch(8);
public static final OBJECT_IDENTIFIER id_cmc_encryptedPOP = id_cmc.subBranch(9);
public static final OBJECT_IDENTIFIER id_cmc_decryptedPOP = id_cmc.subBranch(10);
public static final OBJECT_IDENTIFIER id_cmc_lraPOPWitness = id_cmc.subBranch(11);
public static final OBJECT_IDENTIFIER id_cmc_getCert = id_cmc.subBranch(15);
public static final OBJECT_IDENTIFIER id_cmc_getCRL = id_cmc.subBranch(16);
public static final OBJECT_IDENTIFIER id_cmc_revokeRequest = id_cmc.subBranch(17);
public static final OBJECT_IDENTIFIER id_cmc_regInfo = id_cmc.subBranch(18);
public static final OBJECT_IDENTIFIER id_cmc_responseInfo = id_cmc.subBranch(19);
public static final OBJECT_IDENTIFIER id_cmc_QueryPending = id_cmc.subBranch(21);
public static final OBJECT_IDENTIFIER id_cmc_idPOPLinkRandom = id_cmc.subBranch(22);
public static final OBJECT_IDENTIFIER id_cmc_idPOPLinkWitness = id_cmc.subBranch(23);
public static final OBJECT_IDENTIFIER id_cmc_idConfirmCertAcceptance = id_cmc.subBranch(24);
// rfc 5272
public static final OBJECT_IDENTIFIER id_cmc_statusInfoV2 = id_cmc.subBranch(25);
public static final OBJECT_IDENTIFIER id_cmc_trustedAnchors = id_cmc.subBranch(26);
public static final OBJECT_IDENTIFIER id_cmc_authData = id_cmc.subBranch(27);
public static final OBJECT_IDENTIFIER id_cmc_batchRequests = id_cmc.subBranch(28);
public static final OBJECT_IDENTIFIER id_cmc_batchResponses = id_cmc.subBranch(29);
public static final OBJECT_IDENTIFIER id_cmc_publishCert = id_cmc.subBranch(30);
public static final OBJECT_IDENTIFIER id_cmc_modCertTemplate = id_cmc.subBranch(31);
public static final OBJECT_IDENTIFIER id_cmc_controlProcessed = id_cmc.subBranch(32);
public static final OBJECT_IDENTIFIER id_cmc_popLinkWitnessV2 = id_cmc.subBranch(33);
public static final OBJECT_IDENTIFIER id_cmc_identityProofV2 = id_cmc.subBranch(34);
public static final OBJECT_IDENTIFIER id_cct = PKIX.subBranch(12);
public static final OBJECT_IDENTIFIER id_cct_PKIData = id_cct.subBranch(2);
public static final OBJECT_IDENTIFIER id_cct_PKIResponse = id_cct.subBranch(3);
public static final Tag TAG = new Tag(Tag.Class.UNIVERSAL, 6);
@Override
public Tag getTag() {
return TAG;
}
public static final Form FORM = Form.PRIMITIVE;
private long[] numbers;
/**
* Creates an OBJECT_IDENTIFIER from an array of longs, which constitute
* the numbers that make up the OBJECT IDENTIFIER.
*
* @param numbers Numbers.
*/
public OBJECT_IDENTIFIER(long[] numbers) {
checkLongArray(numbers);
this.numbers = numbers;
}
/**
* Checks the given array of numbers to see if it is a valid OID.
* This is not an exhaustive test, it just looks for obvious problems.
* It will throw an assertion if a problem is found. With DEBUG turned
* off, it just checks for null.
*/
private static void checkLongArray(long[] numbers) {
if (numbers == null) {
throw new NullPointerException();
}
assert (numbers.length >= 2);
assert (numbers[0] == 0 || numbers[0] == 1 || numbers[0] == 2);
}
/**
* Creates an OBJECT_IDENTIFIER from a String version. The proper format
* for the OID string is dotted numbers, for example:
* "3.2.456.53.23.64
".
*
* Because the toString() method here provides a different format, we also
* allow that format, for example:
* "{3 2 456 53 23 64}
".
*
* @param dottedOID OID string.
* @exception NumberFormatException If the given string cannot be
* parsed into an OID.
*/
public OBJECT_IDENTIFIER(String dottedOID) throws NumberFormatException {
if (dottedOID == null || dottedOID.length() == 0) {
throw new NumberFormatException("OID string is zero-length");
}
if (dottedOID.startsWith("{")) {
// input string is of the format provided by OBJECT_IDENTIFIER,toString()
// convert this first to dotted OID
// remove the leading and trailing brackets
dottedOID = dottedOID.substring(1, dottedOID.length() - 1);
// convert spaces to dots
dottedOID = dottedOID.replaceAll(" ", ".");
}
StringTokenizer stok = new StringTokenizer(dottedOID, ".");
numbers = new long[stok.countTokens()];
int i = 0;
while (stok.hasMoreElements()) {
numbers[i++] = Long.parseLong(stok.nextToken());
}
assert (i == numbers.length);
checkLongArray(numbers);
}
public long[] getNumbers() {
return numbers;
}
@Override
public int hashCode() {
int code = 1;
for (int i = 0; i < numbers.length; i++) {
code = (int) (code + numbers[i]) * 10;
}
return code;
}
/**
* Creates a new OBJECT_IDENTIFIER that is a sub-branch of this one.
* For example, if OBJECT_IDENTIFIER oid
has the value
* { 1 3 5 6 },
* then calling oid.subBranch(4)
would return a new
* OBJECT_IDENTIFIER with the value { 1 3 5 6 4 }.
*
* @param num Number.
* @return New sub-branch.
*/
public OBJECT_IDENTIFIER subBranch(long num) {
long[] nums = new long[numbers.length + 1];
System.arraycopy(numbers, 0, nums, 0, numbers.length);
nums[numbers.length] = num;
return new OBJECT_IDENTIFIER(nums);
}
/**
* Creates a new OBJECT_IDENTIFIER that is a sub-branch of this one.
* For example, if OBJECT_IDENTIFIER oid
has the value
* { 1 3 5 6 },
* then calling oid.subBranch(new long[]{ 4, 3})
* would return a new
* OBJECT_IDENTIFIER with the value { 1 3 5 6 4 3}.
*
* @param newNums New numbers.
* @return New sub-branch.
*/
public OBJECT_IDENTIFIER subBranch(long[] newNums) {
long[] nums = new long[numbers.length + newNums.length];
System.arraycopy(numbers, 0, nums, 0, numbers.length);
System.arraycopy(newNums, 0, nums, numbers.length, newNums.length);
return new OBJECT_IDENTIFIER(nums);
}
@Override
public boolean equals(Object obj) {
if (obj == null || !(obj instanceof OBJECT_IDENTIFIER)) {
return false;
}
long[] nums = ((OBJECT_IDENTIFIER) obj).numbers;
if (nums.length != numbers.length) {
return false;
}
for (int i = 0; i < nums.length; i++) {
if (nums[i] != numbers[i]) {
return false;
}
}
return true;
}
@Override
public String toString() {
String ret = "{" + String.valueOf(numbers[0]);
for (int i = 1; i < numbers.length; i++) {
ret = ret + " " + numbers[i];
}
ret += "}";
return ret;
}
public String toDottedString() {
String ret = String.valueOf(numbers[0]);
for (int i = 1; i < numbers.length; i++) {
ret = ret + "." + numbers[i];
}
return ret;
}
@Override
public void encode(OutputStream ostream) throws IOException {
encode(TAG, ostream);
}
private byte[] encodedContents = null;
/**
* Gets the encoding of the contents, or a cached copy.
* Since the content encoding is the same regardless of the Tag,
* this only needs to be computed once.
*/
private byte[] getEncodedContents() {
if (encodedContents == null) {
encodedContents = computeEncodedContents();
}
return encodedContents;
}
// We cache our encoding for a given tag. 99% of the time, only
// one tag will be used for an instance, so we will get a cache hit.
// In the remaining 1%, we'll have to recompute the encoding.
byte[] cachedEncoding = null;
Tag tagForCache = null;
/**
* Returns the encoding for the given tag. If the encoding for
* this tag was previously computed (and no encoding for a different
* tag has since been computed), this method returns a cached copy.
* Otherwise, the encoding will be recomputed.
*/
private byte[] getEncoding(Tag tag) {
if (!tag.equals(tagForCache)) {
// recompute for new tag
ByteArrayOutputStream out = new ByteArrayOutputStream();
ASN1Header head = getHeader(tag);
try {
head.encode(out);
} catch (IOException e) {
throw new RuntimeException("Unable to encode ASN.1 header: " + e.getMessage(), e);
}
out.write(getEncodedContents(), 0, getEncodedContents().length);
tagForCache = tag;
cachedEncoding = out.toByteArray();
}
return cachedEncoding;
}
/**
* Compute the ASN1 header for this tag.
*/
private ASN1Header getHeader(Tag implicitTag) {
return new ASN1Header(implicitTag, FORM, getEncodedContents().length);
}
/**
* Actually computes the encoding of this object identifier.
*/
private byte[] computeEncodedContents() {
ByteArrayOutputStream out = new ByteArrayOutputStream();
// handle first number
assert (numbers.length >= 2);
long n = numbers[0];
assert (n == 0 || n == 1 || n == 2);
long outb = (numbers[0] * 40) + numbers[1];
assert (((byte) outb) == outb);
out.write((byte) outb);
// handle consecutive numbers
for (int i = 2; i < numbers.length; i++) {
n = numbers[i];
assert (n >= 0);
// array of output bytes, in reverse order. 10 bytes, at 7 bits
// per byte, is 70 bits, which is more than enough to handle
// the maximum value of a long, which takes up 63 bits.
byte[] rev = new byte[10];
int idx = 0; // index into reversed bytes
// Create reversed byte list
do {
rev[idx++] = (byte) (n % 128);
n = n / 128;
} while (n > 0);
idx--; // backup to point to last element
// now print them in reverse order
while (idx > 0) {
// all but last byte have MSB==1
out.write(rev[idx--] | 0x80);
}
assert (idx == 0);
// last byte has MSB==0
out.write(rev[0]);
}
return out.toByteArray();
}
@Override
public void encode(Tag implicitTag, OutputStream ostream)
throws IOException {
ostream.write(getEncoding(implicitTag));
}
private static final Template templateInstance = new Template();
public static Template getTemplate() {
return templateInstance;
}
///////////////////////////////////////////////////////////////////////
// OBJECT_IDENTIFIER.Template
//
public static class Template implements ASN1Template {
public Tag getTag() {
return OBJECT_IDENTIFIER.TAG;
}
@Override
public boolean tagMatch(Tag tag) {
return (tag.equals(OBJECT_IDENTIFIER.TAG));
}
public Form getForm() {
return OBJECT_IDENTIFIER.FORM;
}
public boolean formMatch(Form form) {
return (form == OBJECT_IDENTIFIER.FORM);
}
@Override
public ASN1Value decode(InputStream istream)
throws IOException, InvalidBERException {
return decode(getTag(), istream);
}
@Override
public ASN1Value decode(Tag implicitTag, InputStream istream)
throws IOException, InvalidBERException {
try {
ASN1Header head = new ASN1Header(istream);
long remainingContent = head.getContentLength();
// Check the information gleaned from the header
if (!head.getTag().equals(implicitTag)) {
throw new InvalidBERException("Incorrect tag for " +
"OBJECT IDENTIFIER: " + head.getTag());
}
if (head.getForm() != getForm()) {
throw new InvalidBERException("Incorrect form for OBJECT " +
"IDENTIFIER");
}
if (remainingContent < 1) {
throw new InvalidBERException("Invalid 0 length for OBJECT" +
" IDENTIFIER");
}
Vector numberV = new Vector<>();
// handle first byte, which contains first two numbers
byte b = readByte(istream);
remainingContent--;
long num = b % 40;
numberV.addElement(Long.valueOf(b % 40)); // second number
numberV.insertElementAt(Long.valueOf(b / 40), 0); // first number
// handle the rest of the numbers
while (remainingContent > 0) {
num = 0;
// keep reading until MSB == 0
int bitcount = 0;
do {
if ((bitcount += 7) > 63) {
// we're about to overflow our long
throw new InvalidBERException("OBJECT IDENTIFIER " +
"element too long; max is 63 bits");
}
b = readByte(istream);
remainingContent--;
num <<= 7;
num |= (b & 0x7f);
} while ((b & 0x80) != 0);
numberV.addElement(Long.valueOf(num));
}
// convert Vector to array
long numbers[] = new long[numberV.size()];
for (int i = 0; i < numbers.length; i++) {
numbers[i] = numberV.elementAt(i).longValue();
}
// create OBJECT_IDENTIFIER from array
return new OBJECT_IDENTIFIER(numbers);
} catch (InvalidBERException e) {
throw new InvalidBERException(e, "OBJECT IDENTIFIER");
}
}
/**
* Reads in a byte from the stream, throws an InvalidBERException
* if EOF is reached.
*/
private static byte readByte(InputStream istream)
throws InvalidBERException, IOException {
int n = istream.read();
if (n == -1) {
throw new InvalidBERException("End-of-file reached while " +
"decoding OBJECT IDENTIFIER");
}
assert ((n & 0xff) == n);
return (byte) n;
}
} // end of OBJECT_IDENTIFIER.Template
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/asn1/OCTET_STRING.java 0000664 0000000 0000000 00000006650 14565430767 0024424 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.asn1;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
public class OCTET_STRING implements ASN1Value {
public static final Tag TAG = new Tag(Tag.Class.UNIVERSAL, 4);
@Override
public Tag getTag() {
return TAG;
}
public static final Form FORM = Form.PRIMITIVE;
byte[] data;
public OCTET_STRING(byte[] data) {
this.data = data;
}
public byte[] toByteArray() {
return data;
}
@Override
public void encode(OutputStream ostream) throws IOException {
// use getTag() so we can be subclassed
encode(getTag(), ostream);
}
@Override
public void encode(Tag implicitTag, OutputStream ostream)
throws IOException {
ASN1Header head = new ASN1Header(implicitTag, FORM, data.length);
head.encode(ostream);
ostream.write(data);
}
private static final Template templateInstance = new Template();
public static Template getTemplate() {
return templateInstance;
}
public static class Template implements ASN1Template {
public Tag getTag() {
return TAG;
}
@Override
public boolean tagMatch(Tag tag) {
return (TAG.equals(tag));
}
@Override
public ASN1Value decode(InputStream istream)
throws IOException, InvalidBERException {
return decode(getTag(), istream);
}
// this can be overridden by subclasses
protected ASN1Value generateInstance(byte[] bytes) {
return new OCTET_STRING(bytes);
}
// this can be overridden by subclasses
protected String getName() {
return "OCTET_STRING";
}
@Override
public ASN1Value decode(Tag implicitTag, InputStream istream)
throws IOException, InvalidBERException {
try {
ASN1Header head = new ASN1Header(istream);
head.validate(implicitTag);
byte[] data;
if (head.getContentLength() == -1) {
// indefinite length encoding
ASN1Header ahead;
ByteArrayOutputStream bos = new ByteArrayOutputStream();
do {
ahead = ASN1Header.lookAhead(istream);
if (!ahead.isEOC()) {
OCTET_STRING.Template ot = new OCTET_STRING.Template();
OCTET_STRING os = (OCTET_STRING) ot.decode(istream);
bos.write(os.toByteArray());
}
} while (!ahead.isEOC());
// consume EOC
ahead = new ASN1Header(istream);
data = bos.toByteArray();
} else {
data = new byte[(int) head.getContentLength()];
ASN1Util.readFully(data, istream);
}
return generateInstance(data);
} catch (InvalidBERException e) {
throw new InvalidBERException(e, getName());
}
}
} // end of Template
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/asn1/PrintableString.java 0000664 0000000 0000000 00000010101 14565430767 0025551 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.asn1;
import java.io.CharConversionException;
public class PrintableString extends CharacterString {
public PrintableString(char[] chars) throws CharConversionException {
super(chars);
}
public PrintableString(String s) throws CharConversionException {
super(s);
}
@Override
CharConverter getCharConverter() {
return new PrintableConverter();
}
public static final Tag TAG = new Tag(Tag.UNIVERSAL, 19);
public static final Form FORM = Form.PRIMITIVE;
@Override
public Tag getTag() {
return TAG;
}
/**
* Returns a singleton instance of the decoding template for this class.
*
* @return The template.
*/
public static Template getTemplate() {
return templateInstance;
}
private static final Template templateInstance = new Template();
// nested class
public static class Template
extends CharacterString.Template {
@Override
protected Tag getTag() {
return TAG;
}
@Override
public boolean tagMatch(Tag tag) {
return TAG.equals(tag);
}
@Override
protected CharConverter getCharConverter() {
return new PrintableConverter();
}
@Override
protected CharacterString generateInstance(char[] chars)
throws CharConversionException {
return new PrintableString(chars);
}
@Override
protected String typeName() {
return "PrintableString";
}
}
private static class PrintableConverter implements CharConverter {
private static boolean[] isPrintable = new boolean[128];
static {
char b;
for (b = 'A'; b <= 'Z'; b++) {
isPrintable[b] = true;
}
for (b = 'a'; b <= 'z'; b++) {
isPrintable[b] = true;
}
for (b = '0'; b <= '9'; b++) {
isPrintable[b] = true;
}
isPrintable[' '] = true;
isPrintable['\''] = true;
isPrintable['('] = true;
isPrintable[')'] = true;
isPrintable['+'] = true;
isPrintable[','] = true;
isPrintable['-'] = true;
isPrintable['.'] = true;
isPrintable['/'] = true;
isPrintable[':'] = true;
isPrintable['='] = true;
isPrintable['?'] = true;
}
@Override
public char[] byteToChar(byte[] bytes, int offset, int len)
throws CharConversionException {
char[] chars = new char[len];
int c; // char index
int b; // byte index
for (c = 0, b = offset; c < len; b++, c++) {
if ((bytes[b] & 0x80) != 0 || !isPrintable[bytes[b]]) {
/* fix for bug 359010 - don't throw, just skip
* throw new CharConversionException(bytes[b]+ " is not "+
* "a valid character for a PrintableString");
*/
} else {
chars[c] = (char) bytes[b];
}
}
return chars;
}
@Override
public byte[] charToByte(char[] chars, int offset, int len)
throws CharConversionException {
byte[] bytes = new byte[len];
int c; // char index
int b; // byte index
for (c = 0, b = 0; b < len; b++, c++) {
if ((chars[c] & 0xff80) != 0 || !isPrintable[chars[c]]) {
throw new CharConversionException(chars[c] + " is not " +
"a valid character for a PrintableString");
}
bytes[b] = (byte) (chars[c] & 0x7f);
}
return bytes;
}
} // end of char converter
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/asn1/SEQUENCE.java 0000664 0000000 0000000 00000071272 14565430767 0023672 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.asn1;
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
/**
* An ASN.1 SEQUENCE. This class is an ordered collection of ASN.1 values.
* It has an interface similar to a Java Vector
.
* Null entries may be added; they will be skipped when encoded.
*/
public class SEQUENCE extends SET {
public static final Tag TAG = new Tag(Tag.Class.UNIVERSAL, 16);
@Override
public Tag getTag() {
return TAG;
}
public static Template getTemplate() {
return new Template();
}
/**
* Writes the DER encoding to the given output stream,
* using the given implicit tag.
*/
@Override
public void encode(Tag implicitTag, OutputStream ostream)
throws IOException {
BERencode(implicitTag, ostream);
}
/**
* A class for constructing a SEQUENCE
from its BER encoding.
* It is an ordered collection of sub-templates. Each sub-template can be
* marked optional, or a default value can be given.
*/
public static class Template implements ASN1Template {
private ArrayList elements = new ArrayList<>();
private void addElement(Element el) {
elements.add(el);
}
private void insertElementAt(Element e, int index) {
elements.add(index, e);
}
/**
* Adds a sub-template to the end of this SEQUENCE template. For example,
* if the ASN.1 included:
*
*
* MySequence ::= SEQUENCE {
* item SubType,
* ... }
*
*
* the "item" element would be added to the MySequence template with:
*
*
* mySequence.addElement(new SubType.Template());
*
*
* @param t Sub-template.
*/
public void addElement(ASN1Template t) {
addElement(new Element(null, t, false));
}
/**
* Inserts the template at the given index.
*
* @param t Sub-template.
* @param index Index.
*/
public void insertElementAt(ASN1Template t, int index) {
insertElementAt(new Element(null, t, false), index);
}
/**
* Adds a sub-template to the end of this SEQUENCE template, with the
* given implicit tag. For example, if the ASN.1 were:
*
*
* MySequence ::= SEQUENCE {
* item [0] IMPLICIT SubType,
* ... }
*
*
* the "item" element would be added to the MySequence template with:
*
*
* mySequence.addElement(new Tag(0), new SubType.Template());
*
*
* @param implicitTag Implicit tag.
* @param t Sub-template.
*/
public void addElement(Tag implicitTag, ASN1Template t) {
addElement(new Element(implicitTag, t, false));
}
/**
* Inserts the template with the given implicit tag at the given index.
*
* @param implicit Implicit tag.
* @param t Sub-Template.
* @param index Index.
*/
public void insertElementAt(Tag implicit, ASN1Template t,
int index) {
insertElementAt(new Element(implicit, t, false), index);
}
/**
* Adds an optional sub-template. For example, if the ASN.1 were:
*
*
* MySequence ::= SEQUENCE {
* item SubType OPTIONAL,
* ... }
*
*
* the "item" element would be added to the MySequence template with:
*
*
* mySequence.addOptionalElement(new SubType.Template());
*
*
* @param t Optional sub-template.
*/
public void addOptionalElement(ASN1Template t) {
addElement(new Element(null, t, true));
}
/**
* Inserts the optional template at the given index.
*
* @param t Optional sub-template.
* @param index Index.
*/
public void insertOptionalElementAt(ASN1Template t, int index) {
insertElementAt(new Element(null, t, true), index);
}
/**
* Adds an optional sub-template with an implicit tag. For example,
* if the ASN.1 were:
*
*
* MySequence ::= SEQUENCE {
* item [0] IMPLICIT SubType OPTIONAL,
* ... }
*
*
* the "item" element would be added to the MySequence template with:
*
*
* mySequence.addOptionalElement(new SubType.Template());
*
*
* @param implicitTag Implicit tag.
* @param t Optional sub-template.
*/
public void addOptionalElement(Tag implicitTag, ASN1Template t) {
addElement(new Element(implicitTag, t, true));
}
/**
* Inserts the optional template with the given default
* value at the given index.
*
* @param implicit Implicit tag.
* @param t Optional sub-template.
* @param index Index.
*/
public void insertOptionalElementAt(Tag implicit, ASN1Template t,
int index) {
insertElementAt(new Element(implicit, t, true), index);
}
/**
* Adds a sub-template with a default value. For example,
* if the ASN.1 were:
*
*
* MySequence ::= SEQUENCE {
* version INTEGER DEFAULT 1,
* ... }
*
*
* the "item" element would be added to the MySequence template with:
*
*
* mySequence.addElement(new INTEGER.Template(), new INTEGER(1));
*
*
* @param t Sub-template.
* @param def The default value for this field, which will be used if
* no value is supplied by the encoded structure. It must be of
* the same type as what the template would produce.
*/
public void addElement(ASN1Template t, ASN1Value def) {
addElement(new Element(null, t, def));
}
/**
* Inserts the template with the given default
* value at the given index.
*
* @param t Sub-template.
* @param def Default value.
* @param index Index.
*/
public void insertElementAt(ASN1Template t, ASN1Value def, int index) {
insertElementAt(new Element(null, t, def), index);
}
/**
* Adds a sub-template with a default value and an implicit tag.
* For example, if the ASN.1 were:
*
*
* MySequence ::= SEQUENCE {
* version [0] IMPLICIT INTEGER DEFAULT 1,
* ... }
*
*
* the "item" element would be added to the MySequence template with:
*
*
* mySequence.addElement(new Tag(0), new INTEGER.Template(),
* new INTEGER(1));
*
*
* @param implicitTag Implicit tag.
* @param t Sub-template.
* @param def The default value for this field, which will be used if
* no value is supplied by the encoded structure. It must be of
* the same type as what the template would produce.
*/
public void addElement(Tag implicitTag, ASN1Template t, ASN1Value def) {
addElement(new Element(implicitTag, t, def));
}
/**
* Inserts the template with the given implicit tag and given default
* value at the given index.
*
* @param implicit Implicit tag.
* @param t Sub-template.
* @param def Default value.
* @param index Index.
*/
public void insertElementAt(Tag implicit, ASN1Template t, ASN1Value def,
int index) {
insertElementAt(new Element(implicit, t, def), index);
}
/**
* Returns the implicit tag of the item stored at the given index.
* May be NULL if no implicit tag was specified.
*
* @param index Index.
* @return Tag.
*/
public Tag implicitTagAt(int index) {
return elements.get(index).getImplicitTag();
}
/**
* Returns the sub-template stored at the given index.
*
* @param index Index.
* @return Sub-template.
*/
public ASN1Template templateAt(int index) {
return elements.get(index).getTemplate();
}
/**
* Returns whether the sub-template at the given index is optional.
*
* @param index Index.
* @return True if the sub-template is optional.
*/
public boolean isOptionalAt(int index) {
return elements.get(index).isOptional();
}
/**
* Returns the default value for the sub-template at the given index.
* May return NULL if no default value was specified.
*
* @param index Index.
* @return Default value.
*/
public ASN1Value defaultAt(int index) {
return elements.get(index).getDefault();
}
/**
* @return The number of elements in this SEQUENCE template.
*/
public int size() {
return elements.size();
}
/**
* Removes all sub-templates from this SEQUENCE template.
*/
public void removeAllElements() {
elements.clear();
}
/**
* Removes the sub-template at the given index.
*
* @param index Index.
*/
public void removeElementAt(int index) {
elements.remove(index);
}
Tag getTag() {
return SEQUENCE.TAG;
}
@Override
public boolean tagMatch(Tag tag) {
return (tag.equals(SEQUENCE.TAG));
}
/**
* Decodes a SEQUENCE from its BER encoding.
*
* @param istream Input stream.
*/
@Override
public ASN1Value decode(InputStream istream)
throws IOException, InvalidBERException {
return decode(getTag(), istream);
}
/**
* Decodes a SEQUENCE from its BER encoding, where the SEQUENCE itself has
* an implicit tag.
*
* @param tag Tag.
* @param istream Input stream.
*/
@Override
public ASN1Value decode(Tag tag, InputStream istream)
throws IOException, InvalidBERException {
int index = 0;
try {
ASN1Header header = new ASN1Header(istream);
header.validate(tag, Form.CONSTRUCTED);
// will be -1 for indefinite encoding
long remainingContent = header.getContentLength();
boolean repeatableElement = false;
SEQUENCE seq = new SEQUENCE();
ASN1Header lookAhead = null;
// go through the whole template
for (index = 0; index < size(); index++) {
// find out about the next item
if (remainingContent == 0) {
lookAhead = null;
} else {
// remainingContent > 0 or remainingContent == -1, which means
// indefinite encoding.
lookAhead = ASN1Header.lookAhead(istream);
}
// skip over items that don't match. Hopefully they are
// optional or have a default. Otherwise, it's an error.
Element e = elements.get(index);
if ((lookAhead == null) || lookAhead.isEOC() ||
!e.tagMatch(lookAhead.getTag())) {
if (e.isRepeatable()) {
repeatableElement = true;
} else if (e.isOptional()) {
// put an empty entry into the SEQUENCE
seq.addElement(null);
} else if (e.getDefault() != null) {
// use the default
seq.addElement(e.getDefault());
} else {
String tagDesc;
if (lookAhead == null) {
tagDesc = "(null)";
} else {
tagDesc = lookAhead.getTag().toString();
}
throw new InvalidBERException("Missing item #" + index +
": found " + tagDesc);
}
continue;
}
// Decode this element
ASN1Template t = e.getTemplate();
ASN1Value val;
try (CountingStream countstream = new CountingStream(istream)) {
if (e.getImplicitTag() == null) {
val = t.decode(countstream);
} else {
val = t.decode(e.getImplicitTag(), countstream);
}
// Decrement remaining count
long len = countstream.getNumRead();
if (remainingContent != -1) {
if (remainingContent < len) {
// this item went past the end of the SEQUENCE
throw new InvalidBERException("Item went " +
(len - remainingContent) + " bytes past the end of" +
" the SEQUENCE");
}
remainingContent -= len;
}
}
// Store this element in the SEQUENCE
if (e.producesOutput()) {
if (e.getImplicitTag() == null) {
// no implicit tag
seq.addElement(val);
} else {
// there is an implicit tag
seq.addElement(e.getImplicitTag(), val);
}
}
// If this element is repeatable, don't go on to the next element
if (e.isRepeatable()) {
repeatableElement = true;
index--;
}
}
if (remainingContent > 0) {
throw new InvalidBERException("SEQUENCE is " + remainingContent +
" bytes longer than expected");
}
assert (remainingContent == 0 || remainingContent == -1);
// If this was indefinite-length encoding, consume the end-of-contents
if (remainingContent == -1) {
lookAhead = new ASN1Header(istream);
if (!lookAhead.isEOC()) {
throw new InvalidBERException("No end-of-contents marker");
}
}
// Make sure we stayed in sync
if (!repeatableElement) {
assert (index == seq.size());
}
return seq;
} catch (InvalidBERException e) {
e.append("SEQUENCE(item #" + index + ")");
throw e;
}
}
/**
* An element of a SEQUENCE template. For each sub-template, contains the
* template, its optionality, its implicit tag, and its default value.
*/
static class Element {
/**
* Creates a new element, which may or may not be optional.
*
* @param implicitTag Implicit tag.
* @param type Type.
* @param optional Optional.
*/
public Element(Tag implicitTag, ASN1Template type, boolean optional) {
this(implicitTag, type, optional, true);
}
/**
* Creates a new element, which may or may not be optional.
*
* @param implicitTag Implicit tag.
* @param type Type.
* @param optional Optional.
* @param doesProduceOutput True if produces output.
*/
public Element(Tag implicitTag, ASN1Template type, boolean optional,
boolean doesProduceOutput) {
this.type = type;
defaultVal = null;
this.optional = optional;
this.implicitTag = implicitTag;
this.doesProduceOutput = doesProduceOutput;
}
/**
* Creates a new element with a default value.
*
* @param implicitTag Implicit tag.
* @param type Type.
* @param defaultVal Default value.
*/
public Element(Tag implicitTag, ASN1Template type, ASN1Value defaultVal) {
this.type = type;
this.defaultVal = defaultVal;
optional = false;
this.implicitTag = implicitTag;
}
private boolean doesProduceOutput = true;
boolean producesOutput() {
return doesProduceOutput;
}
// repeatability is provided to allow for SEQUENCE OF SIZE
// constructs. It is package private.
private boolean repeatable;
void makeRepeatable() {
repeatable = true;
}
boolean isRepeatable() {
return repeatable;
}
private boolean optional;
public boolean isOptional() {
return optional;
}
private Tag implicitTag = null;
public Tag getImplicitTag() {
return implicitTag;
}
public boolean tagMatch(Tag tag) {
if (implicitTag != null) {
return (implicitTag.equals(tag));
} else {
return type.tagMatch(tag);
}
}
private ASN1Template type;
public ASN1Template getTemplate() {
return type;
}
private ASN1Value defaultVal = null;
public ASN1Value getDefault() {
return defaultVal;
}
}
} // End of SEQUENCE.Template
/**
* A Template for decoding SEQUENCE OF values. The main difference between
* a SEQUENCE.Template and a SEQUENCE.OF_Template is that a regular template
* specifies the exact ordering, number, and type of elements of the sequence,
* while
* an OF_Template has an indefinite number of elements, all the same type.
* For example, given:
*
*
* MyType ::= SEQUENCE OF Extension
*
*
* a MyType could be decoded with:
*
*
* SEQUENCE.OF_Template myTypeTemplate = new SEQUENCE.OF_Template( new
* Extension.Template) );
* SEQUENCE seq = (SEQUENCE) myTypeTemplate.decode(someInputStream);
*
*
* The number of Extension
s actually decoded could be found
* with seq.size()
.
*/
public static class OF_Template implements ASN1Template {
private OF_Template() {
}
Template template; // a normal SEQUENCE template
public OF_Template(ASN1Template type) {
template = new Template();
Template.Element el = new Template.Element(null, type, true); //optional
el.makeRepeatable();
template.addElement(el);
}
public static OF_Template makeOutputlessOFTemplate(ASN1Template type) {
OF_Template t = new OF_Template();
t.template = new Template();
Template.Element el = new Template.Element(null, type, true, false);
el.makeRepeatable();
t.template.addElement(el);
return t;
}
@Override
public boolean tagMatch(Tag tag) {
return TAG.equals(tag);
}
/**
* Decodes a SEQUENCE OF from an input stream.
*/
@Override
public ASN1Value decode(InputStream istream)
throws IOException, InvalidBERException {
return template.decode(istream);
}
/**
* Decodes a SEQUENCE OF with an implicit tag from an input stream.
*/
@Override
public ASN1Value decode(Tag implicitTag, InputStream istream)
throws IOException, InvalidBERException {
return template.decode(implicitTag, istream);
}
}
public static void main(String args[]) {
try {
if (args.length > 0) {
// input
Template type = new Template();
type.addOptionalElement(new Tag(15), new INTEGER.Template());
type.addElement(new Tag(16), new INTEGER.Template(),
new INTEGER(42));
type.addElement(new INTEGER.Template());
type.addElement(new BOOLEAN.Template());
type.addElement(new INTEGER.Template());
type.addOptionalElement(new Tag(12), new INTEGER.Template());
type.addElement(new BOOLEAN.Template());
type.addElement(new Tag(13), new INTEGER.Template(),
new INTEGER(53));
type.addElement(new INTEGER.Template());
type.addElement(new INTEGER.Template());
type.addOptionalElement(new Tag(14), new INTEGER.Template());
type.addElement(new OBJECT_IDENTIFIER.Template());
type.addElement(new NULL.Template());
type.addElement(new EXPLICIT.Template(
new Tag(27), new INTEGER.Template()));
type.addElement(new ENUMERATED.Template());
type.addElement(new OCTET_STRING.Template());
type.addElement(new IA5String.Template());
CHOICE.Template choice = new CHOICE.Template();
choice.addElement(new Tag(23), new INTEGER.Template());
choice.addElement(new BOOLEAN.Template());
type.addElement(choice);
type.addElement(new BIT_STRING.Template());
type.addElement(new ANY.Template());
type.addElement(new PrintableString.Template());
type.addElement(new OF_Template(new INTEGER.Template()));
type.addElement(new OF_Template(new INTEGER.Template()));
byte[] stuff;
try (FileInputStream fin = new FileInputStream(args[0])) {
System.out.println("Available: " + fin.available());
stuff = new byte[fin.available()];
ASN1Util.readFully(stuff, fin);
}
SEQUENCE s = null;
for (int i = 0; i < 1; i++) {
s = (SEQUENCE) type.decode(new ByteArrayInputStream(stuff));
}
for (int i = 0; i < s.size(); i++) {
ASN1Value v = s.elementAt(i);
if (v instanceof ENUMERATED) {
ENUMERATED en = (ENUMERATED) v;
System.out.println("ENUMERATED: " + en);
} else if (v instanceof INTEGER) {
INTEGER in = (INTEGER) v;
System.out.println("INTEGER: " + in);
} else if (v instanceof BOOLEAN) {
BOOLEAN bo = (BOOLEAN) v;
System.out.println("BOOLEAN: " + bo);
} else if (v instanceof OBJECT_IDENTIFIER) {
OBJECT_IDENTIFIER oid = (OBJECT_IDENTIFIER) v;
System.out.println("OID: " + oid);
} else if (v instanceof NULL) {
NULL n = (NULL) v;
System.out.println("NULL");
} else if (v instanceof EXPLICIT) {
EXPLICIT ex = (EXPLICIT) v;
INTEGER in = (INTEGER) ex.getContent();
System.out.println("EXPLICIT [" + ex.getTag() + "]: " +
"INTEGER: " + in);
} else if (v instanceof OCTET_STRING) {
OCTET_STRING os = (OCTET_STRING) v;
byte[] bytes = os.toByteArray();
System.out.print("OCTET_STRING: ");
for (int j = 0; j < bytes.length; j++) {
System.out.print(bytes[j] + " ");
}
System.out.println("");
} else if (v instanceof CharacterString) {
CharacterString cs = (CharacterString) v;
System.out.println("String: " + cs);
} else if (v instanceof BIT_STRING) {
BIT_STRING bs = (BIT_STRING) v;
System.out.print("BIT_STRING: padCount=" +
bs.getPadCount() + " : ");
byte[] bits = bs.getBits();
for (int j = 0; j < bits.length; j++) {
System.out.print(bits[j] + " ");
}
System.out.println("");
} else if (v instanceof ANY) {
ANY any = (ANY) v;
Tag tag = any.getTag();
System.out.println("Got ANY, tag is " + tag);
ByteArrayInputStream bos = new ByteArrayInputStream(any.getEncoded());
INTEGER in = (INTEGER) new INTEGER.Template().decode(bos);
System.out.println(" INTEGER: " + in);
} else if (v instanceof SEQUENCE) {
SEQUENCE seq = (SEQUENCE) v;
System.out.println("SEQUENCE: ");
for (int j = 0; j < seq.size(); j++) {
INTEGER in = (INTEGER) seq.elementAt(j);
System.out.println(" INTEGER: " + in);
}
} else {
System.out.println("Unknown value");
}
}
} else {
// output
SEQUENCE seq = new SEQUENCE();
seq.addElement(new INTEGER(5));
seq.addElement(new BOOLEAN(true));
seq.addElement(new INTEGER(-322));
seq.addElement(new BOOLEAN(false));
seq.addElement(new INTEGER(0));
seq.addElement(new INTEGER("2934293834242"));
seq.addElement(new OBJECT_IDENTIFIER(
new long[] { 1, 2, 127, 563, 1231982 }));
seq.addElement(new NULL());
seq.addElement(new EXPLICIT(new Tag(27), new INTEGER(39)));
seq.addElement(new ENUMERATED(983));
seq.addElement(new OCTET_STRING(new byte[] {
(byte) 0x0, (byte) 0xff, (byte) 0xcc }));
seq.addElement(new IA5String("foobar"));
seq.addElement(new Tag(23), new INTEGER(234));
//seq.addElement( new BOOLEAN(false) );
byte[] bits = new byte[] { (byte) 0x80, (byte) 0xff, (byte) 0x0f };
seq.addElement(new BIT_STRING(bits, 3));
seq.addElement(new INTEGER(82734));
seq.addElement(new PrintableString("I'm printable??"));
SEQUENCE nested = new SEQUENCE();
nested.addElement(new INTEGER(5));
nested.addElement(new INTEGER(6));
seq.addElement(nested);
nested = new SEQUENCE();
seq.addElement(nested);
seq.encode(System.out);
System.out.flush();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/asn1/SET.java 0000664 0000000 0000000 00000075604 14565430767 0023120 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.asn1;
import java.io.BufferedInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Vector;
/**
* An ASN.1 SET, which is an unordered collection of ASN.1 values.
* It has an interface like a Java Vector, but the ordering is arbitrary.
* Null entries may be added; they will be skipped when encoding.
*/
public class SET implements ASN1Value {
public static final Tag TAG = new Tag(Tag.Class.UNIVERSAL, 17);
@Override
public Tag getTag() {
return TAG;
}
protected static final Form FORM = Form.CONSTRUCTED;
// The elements of the set
protected Vector elements = new Vector<>();
private void addElement(Element e) {
elements.addElement(e);
}
private void insertElementAt(Element e, int index) {
elements.insertElementAt(e, index);
}
/**
* Adds an element to this SET.
*
* @param v Element.
*/
public void addElement(ASN1Value v) {
addElement(new Element(v));
}
/**
* Adds an element to this SET with the given implicit tag. For example,
* if the ASN.1 were:
*
*
* MyType ::= SET {
* item [0] IMPLICIT INTEGER,
* ... }
*
*
* then the "item" element could be added (with a sample value of 45)
* to the SET with:
*
*
* myTypeInstance.addElement(new Tag(0), new INTEGER(45));
*
*
* @param implicitTag Implicit tag.
* @param v Element.
*/
public void addElement(Tag implicitTag, ASN1Value v) {
addElement(new Element(implicitTag, v));
}
/**
* Inserts an element at the given index.
*
* @param v Element.
* @param index Index.
*/
public void insertElementAt(ASN1Value v, int index) {
insertElementAt(new Element(v), index);
}
/**
* Inserts an element with the given implicit tag at the given index.
*
* @param implicitTag Implicit tag.
* @param v Element.
* @param index Index.
*/
public void insertElementAt(Tag implicitTag, ASN1Value v, int index) {
insertElementAt(new Element(implicitTag, v), index);
}
/**
* Returns the element at the given index in the SET.
*
* @param index Index.
* @return Element.
*/
public ASN1Value elementAt(int index) {
return elements.elementAt(index).getValue();
}
/**
* Returns the tag of the element at the given index. If the element
* has an implicit tag, that is returned. Otherwise, the tag of the
* underlying type is returned.
*
* @param index Index.
* @return Tag.
*/
public Tag tagAt(int index) {
Tag implicit = elements.elementAt(index).getImplicitTag();
return implicit == null ? elementAt(index).getTag() : implicit;
}
/**
* Returns the element with the given Tag, or null if no element exists
* with the given tag.
*
* @param tag Tag.
* @return Element.
*/
public ASN1Value elementWithTag(Tag tag) {
// hmmm...linear search for now, should use hashtable later
int size = elements.size();
for (int i = 0; i < size; i++) {
Element e = elements.elementAt(i);
if (e.getTag().equals(tag)) {
return e.getValue();
}
}
return null;
}
/**
* @return The number of elements in this SET.
*/
public int size() {
return elements.size();
}
/**
* Removes all elements from this SET.
*/
public void removeAllElements() {
elements.removeAllElements();
}
/**
* Removes the element from the specified index.
*
* @param index Index.
*/
public void removeElementAt(int index) {
elements.removeElementAt(index);
}
/**
* Writes the DER encoding to the given output stream.
*
* @param ostream Output stream.
*/
@Override
public void encode(OutputStream ostream)
throws IOException {
encode(getTag(), ostream);
}
/**
* Writes the DER encoding to the given output stream,
* using the given implicit tag. To satisfy DER encoding rules,
* the elements will be re-ordered either by tag or lexicographically.
*
* @param implicitTag Implicit tag.
* @param ostream Output stream.
*/
@Override
public void encode(Tag implicitTag, OutputStream ostream)
throws IOException {
// what ordering method?
boolean lexOrdering;
if (elements.size() < 2) {
// doesn't matter, only one element
lexOrdering = true;
} else if (tagAt(0).equals(tagAt(1))) {
// tags are the same, lexicographic ordering
lexOrdering = true;
} else {
// tags are different, order by tag
lexOrdering = false;
}
// compute and order contents
int numElements = elements.size();
int totalBytes = 0;
Vector encodings = new Vector<>(numElements);
Vector tags = new Vector<>(numElements);
int i;
for (i = 0; i < numElements; i++) {
// if an entry is null, just skip it
if (elementAt(i) != null) {
byte[] enc = ASN1Util.encode(tagAt(i), elementAt(i));
totalBytes += enc.length;
if (lexOrdering) {
insertInOrder(encodings, enc);
} else {
insertInOrder(encodings, enc, tags, (int) tagAt(i).getNum());
}
}
}
// write header
ASN1Header header = new ASN1Header(implicitTag, FORM, totalBytes);
header.encode(ostream);
// write contents in order
for (i = 0; i < numElements; i++) {
ostream.write(encodings.elementAt(i));
}
}
/**
* Encodes this SET without re-ordering it. This may violate
* DER, but it is within BER.
*
* @param implicitTag Implicit tag.
* @param ostream Output stream.
* @throws IOException If an error occurred.
*/
public void BERencode(Tag implicitTag, OutputStream ostream)
throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
// compute contents
int size = elements.size();
for (int i = 0; i < size; i++) {
ASN1Value el = elementAt(i);
if (el != null) {
el.encode(tagAt(i), bos);
}
}
byte[] bytes = bos.toByteArray();
// write header
ASN1Header header = new ASN1Header(implicitTag, FORM, bytes.length);
header.encode(ostream);
// write contents
ostream.write(bytes);
}
// performs ascending lexicographic ordering
// linear search, but number of items is usually going to be small.
private static void insertInOrder(Vector encs, byte[] enc) {
int size = encs.size();
// find the lowest item that we are less than or equal to
int i;
for (i = 0; i < size; i++) {
if (compare(enc, encs.elementAt(i)) < 1) {
break;
}
}
// insert ourself before this item
encs.insertElementAt(enc, i);
}
// performs ascending ordering by tag
// linear search, but number of items is usually going to be small.
private static void insertInOrder(Vector encs, byte[] enc, Vector tags,
int tag) {
int size = encs.size();
// find the lowest item that we are less than or equal to
int i;
for (i = 0; i < size; i++) {
if (tag <= tags.elementAt(i).intValue()) {
break;
}
}
// insert ourself before this item
encs.insertElementAt(enc, i);
tags.insertElementAt(Integer.valueOf(i), i);
}
// compares two byte arrays
// returns 1 if left > right, -1 if left < right, 0 if left == right
private static int compare(byte[] left, byte[] right) {
int min = (left.length < right.length) ? left.length : right.length;
for (int i = 0; i < min; i++) {
if ((left[i] & 0xff) < (right[i] & 0xff)) {
return -1;
} else if ((left[i] & 0xff) > (right[i] & 0xff)) {
return 1;
}
}
// equal up to the minimal endpoint
if (left.length > min) {
assert (right.length == min);
return 1;
}
if (right.length > min) {
assert (left.length == min);
return -1;
}
return 0;
}
/**
* An element of a SET
*/
static class Element {
/**
* Makes a new SET element from the given value.
*/
public Element(ASN1Value val) {
this.val = val;
}
/**
* Makes a new SET element from the given value with the given
* implicit tag.
*/
public Element(Tag implicitTag, ASN1Value val) {
this.val = val;
this.implicitTag = implicitTag;
}
private ASN1Value val;
/**
* Returns the value of this SET element.
*/
public ASN1Value getValue() {
return val;
}
/**
* Returns the tag that actually shows up in the encoding.
* If there is an implicit tag, it will be used. Otherwise,
* it will be the base tag for the value.
*/
public Tag getTag() {
return implicitTag == null ? val.getTag() : implicitTag;
}
private Tag implicitTag = null;
/**
* Returns the implicit tag for this value, if there is one.
* If not, returns null.
*/
public Tag getImplicitTag() {
return implicitTag;
}
}
/**
* SET.Template
* This class is used for decoding DER-encoded SETs.
*/
public static class Template implements ASN1Template {
private Vector elements = new Vector<>();
private void addElement(Element e) {
elements.addElement(e);
}
private void insertElementAt(Element e, int index) {
elements.insertElementAt(e, index);
}
/**
* Adds a sub-template to the end of this SET template. For example,
* if the ASN.1 included:
*
*
* MySet ::= SET {
* item SubType,
* ... }
*
*
* the "item" element would be added to the MySet template with:
*
*
* mySet.addElement(new SubType.Template());
*
*
* @param t Sub-template.
*/
public void addElement(ASN1Template t) {
addElement(new Element(TAG, t, false));
}
/**
* Inserts the template at the given index.
*
* @param t Sub-template.
* @param index Index.
*/
public void insertElementAt(ASN1Template t, int index) {
insertElementAt(new Element(TAG, t, false), index);
}
/**
* Adds a sub-template with the given implicit tag to the end of this
* SET template. For example, if the ASN.1 included:
*
*
* MySet ::= SET {
* item [0] IMPLICIT SubType,
* ... }
*
*
* the "item" element would be added to the MySet template with:
*
*
* mySet.addElement(new Tag(0), new SubType.Template());
*
*
* @param implicit Implicit tag.
* @param t Sub-template.
*/
public void addElement(Tag implicit, ASN1Template t) {
addElement(new Element(implicit, t, false));
}
/**
* Inserts the template with the given implicit tag at the given index.
*
* @param implicit Implicit tag.
* @param t Sub-template.
* @param index Index.
*/
public void insertElementAt(Tag implicit, ASN1Template t,
int index) {
insertElementAt(new Element(implicit, t, false), index);
}
/**
* Adds an optional sub-template to the end
* of this SET template. For example, if the ASN.1 included:
*
*
* MySet ::= SET {
* item SubType OPTIONAL,
* ... }
*
*
* the "item" element would be added to the MySet template with:
*
*
* mySet.addOptionalElement(new SubType.Template());
*
*
* @param t Optional sub-template.
*/
public void addOptionalElement(ASN1Template t) {
addElement(new Element(TAG, t, true));
}
/**
* Inserts the optional template at the given index.
*
* @param t Optional sub-template.
* @param index Index.
*/
public void insertOptionalElementAt(ASN1Template t, int index) {
insertElementAt(new Element(null, t, true), index);
}
/**
* Adds an optional sub-template with the given implicit tag to the end
* of this SET template. For example, if the ASN.1 included:
*
*
* MySet ::= SET {
* item [0] IMPLICIT SubType OPTIONAL,
* ... }
*
*
* the "item" element would be added to the MySet template with:
*
*
* mySet.addOptionalElement(new Tag(0), new SubType.Template());
*
*
* @param implicit Implicit tag.
* @param t Optional sub-template.
*/
public void addOptionalElement(Tag implicit, ASN1Template t) {
addElement(new Element(implicit, t, true));
}
/**
* Inserts the optional template with the given default
* value at the given index.
*
* @param implicit Implicit tag.
* @param t Optional sub-template.
* @param index Index.
*/
public void insertOptionalElementAt(Tag implicit, ASN1Template t,
int index) {
insertElementAt(new Element(implicit, t, true), index);
}
/**
* Adds a sub-template with the given default value to the end
* of this SET template. For example, if the ASN.1 included:
*
*
* MySet ::= SET {
* item INTEGER DEFAULT (5),
* ... }
*
*
* the "item" element would be added to the MySet template with:
*
*
* mySet.addElement(new SubType.Template(), new INTEGER(5));
*
*
* @param t Sub-template.
* @param def Default value.
*/
public void addElement(ASN1Template t, ASN1Value def) {
addElement(new Element(TAG, t, def));
}
/**
* Inserts the template with the given default
* value at the given index.
*
* @param t Sub-template.
* @param def Default value.
* @param index Index.
*/
public void insertElementAt(ASN1Template t, ASN1Value def, int index) {
insertElementAt(new Element(null, t, def), index);
}
/**
* Adds a sub-template with the given default value and implicit tag to
* the end of this SET template. For example, if the ASN.1 included:
*
*
* MySet ::= SET {
* item [0] IMPLICIT INTEGER DEFAULT (5),
* ... }
*
*
* the "item" element would be added to the MySet template with:
*
*
* mySet.addElement(new Tag(0), new SubType.Template(), new INTEGER(5));
*
*
* @param implicit Implicit tag.
* @param t Sub-template.
* @param def Default value.
*/
public void addElement(Tag implicit, ASN1Template t, ASN1Value def) {
addElement(new Element(implicit, t, def));
}
/**
* Inserts the template with the given implicit tag and given default
* value at the given index.
*
* @param implicit Implicit tag.
* @param t Sub-template.
* @param def Default value.
* @param index Index.
*/
public void insertElementAt(Tag implicit, ASN1Template t, ASN1Value def,
int index) {
insertElementAt(new Element(implicit, t, def), index);
}
/**
* Returns the implicit tag of the item stored at the given index.
* May be NULL if no implicit tag was specified.
*
* @param index Index.
* @return Implicit tag.
*/
public Tag implicitTagAt(int index) {
return elements.elementAt(index).getImplicitTag();
}
/**
* Returns the sub-template stored at the given index.
*
* @param index Index.
* @return Sub-template.
*/
public ASN1Template templateAt(int index) {
return elements.elementAt(index).getTemplate();
}
/**
* Returns true
if the sub-template at the given index
* is optional.
*
* @param index Index.
* @return True if sub-template is optional.
*/
public boolean isOptionalAt(int index) {
return elements.elementAt(index).isOptional();
}
private boolean isRepeatableAt(int index) {
return elements.elementAt(index).isRepeatable();
}
/**
* Returns the default value for the sub-template at the given index.
* May return NULL if no default value was specified.
*
* @param index Index.
* @return Default value.
*/
public ASN1Value defaultAt(int index) {
return elements.elementAt(index).getDefault();
}
/**
* @return The number of elements in the SET.
*/
public int size() {
return elements.size();
}
public void removeAllElements() {
elements.removeAllElements();
}
public void removeElementAt(int index) {
elements.removeElementAt(index);
}
private Tag getTag() {
return SET.TAG;
}
/**
* Determines whether the given tag satisfies this template.
*
* @param tag Tag.
* @return True if tag satisfies this template.
*/
@Override
public boolean tagMatch(Tag tag) {
return (tag.equals(SET.TAG));
}
/**
* Decodes the input stream into a SET value.
*
* @param istream Input stream.
* @return Decoded SET value.
*/
@Override
public ASN1Value decode(InputStream istream)
throws IOException, InvalidBERException {
return decode(getTag(), istream);
}
/**
* Decodes the input stream into a SET value with the given implicit
* tag.
*
* @param tag Implicit tag.
* @param istream Input stream.
* @return Decoded SET value.
*/
@Override
public ASN1Value decode(Tag tag, InputStream istream)
throws IOException, InvalidBERException {
try {
ASN1Header header = new ASN1Header(istream);
header.validate(tag, Form.CONSTRUCTED);
// remainingContent will be -1 for indefinite length encoding
long remainingContent = header.getContentLength();
SET set = new SET();
ASN1Header lookAhead;
boolean[] found = new boolean[elements.size()];
// while content remains, try to decode it
while (remainingContent > 0 || remainingContent == -1) {
// find out about the next item
lookAhead = ASN1Header.lookAhead(istream);
// if we found the end-of-content marker, we're done
if (lookAhead.isEOC()) {
if (remainingContent != -1) {
throw new InvalidBERException("Unexpected end-of-content" +
"marker");
}
lookAhead = new ASN1Header(istream);
break;
}
// Find the element with the matching tag
int index = findElementByTag(lookAhead.getTag());
if (index == -1) {
// element not found
throw new InvalidBERException("Unexpected Tag in SET: " +
lookAhead.getTag());
}
Element e = elements.elementAt(index);
if (found[index] && !e.isRepeatable()) {
// element already found, and it's not repeatable
throw new InvalidBERException("Duplicate Tag in SET: " +
lookAhead.getTag());
}
// mark this element as found
found[index] = true;
// Decode this element
ASN1Template t = e.getTemplate();
ASN1Value val;
try (CountingStream countstream = new CountingStream(istream)) {
if (e.getImplicitTag() == null) {
val = t.decode(countstream);
} else {
val = t.decode(e.getImplicitTag(), countstream);
}
// Decrement remaining count
long len = countstream.getNumRead();
if (remainingContent != -1) {
if (remainingContent < len) {
// this item went past the end of the SET
throw new InvalidBERException("Item went " +
(len - remainingContent) + " bytes past the end of" +
" the SET");
}
remainingContent -= len;
}
}
// Store this element in the SET
SET.Element se;
if (e.getImplicitTag() == null) {
// no implicit tag
se = new SET.Element(val);
} else {
// there is an implicit tag
se = new SET.Element(e.getImplicitTag(), val);
}
set.addElement(se);
}
// We check for this after we read in each item, so this shouldn't
// happen
assert (remainingContent == 0 || remainingContent == -1);
// Deal with elements that weren't present.
int size = elements.size();
for (int i = 0; i < size; i++) {
if (!found[i]) {
if (isOptionalAt(i) || isRepeatableAt(i)) {
// no problem
} else if (defaultAt(i) != null) {
set.addElement(new SET.Element(defaultAt(i)));
} else {
throw new InvalidBERException("Field not found in SET");
}
}
}
return set;
} catch (InvalidBERException e) {
throw new InvalidBERException(e, "SET");
}
}
/**
* Returns the index in the vector of the type with this tag and class,
* or -1 if not found.
* lame linear search - but we're dealing with small numbers of elements,
* so it's probably not worth it to use a hashtable
*
* @param tag Tag.
*/
private int findElementByTag(Tag tag) {
int size = elements.size();
for (int i = 0; i < size; i++) {
Element e = elements.elementAt(i);
if (e.tagMatch(tag)) {
// match!
return i;
}
}
// no match
return -1;
}
/**
* An element of a SET template.
*/
public static class Element {
public Element(Tag implicitTag, ASN1Template type, boolean optional) {
this.type = type;
defaultVal = null;
this.optional = optional;
this.implicitTag = implicitTag;
}
public Element(Tag implicitTag, ASN1Template type, ASN1Value defaultVal) {
this.type = type;
this.defaultVal = defaultVal;
optional = false;
this.implicitTag = implicitTag;
}
// Repeatability is used for SET OF. It is package private.
private boolean repeatable;
void makeRepeatable() {
repeatable = true;
}
boolean isRepeatable() {
return repeatable;
}
private boolean optional;
public boolean isOptional() {
return optional;
}
private Tag implicitTag = null;
public Tag getImplicitTag() {
return implicitTag;
}
/**
* Determines whether the given tag satisfies this SET element.
*
* @param tag Tag.
* @return True if tag satisfies SET.
*/
public boolean tagMatch(Tag tag) {
return implicitTag == null ? type.tagMatch(tag) : (implicitTag.equals(tag));
}
private ASN1Template type;
/**
* @return The template for this element.
*/
public ASN1Template getTemplate() {
return type;
}
private ASN1Value defaultVal = null;
/**
* Returns the default value for this element, if one exists.
* Otherwise, returns null.
*
* @return Default value.
*/
public ASN1Value getDefault() {
return defaultVal;
}
}
} // End of SET.Template
/**
* A Template for decoding SET OF values.
* Use this if you have a SIZE qualifier on your SET OF.
* The SET will consume as many instances of type as it can, rather than
* stopping after the first one. This is equivalent to SIZE (0..MAX).
* If you need something more restrictive, you can look at what gets parsed
* and decide whether it's OK or not yourself.
*/
public static class OF_Template implements ASN1Template {
private Template template; // a normal SET template
/**
* Creates an OF_Template with the given type. For example:
*
*
* MySet ::= SET OF INTEGER;
*
*
* A MySet
template would be constructed with:
*
*
* SET.OF_Template mySetTemplate = new SET.OF_Template(new INTEGER.Template());
*
*
* @param type Type.
*/
public OF_Template(ASN1Template type) {
template = new Template();
Template.Element el = new Template.Element(null, type, false);
el.makeRepeatable();
template.addElement(el);
}
@Override
public boolean tagMatch(Tag tag) {
return TAG.equals(tag);
}
/**
* Decodes a SET OF
from its BER encoding.
*/
@Override
public ASN1Value decode(InputStream istream)
throws IOException, InvalidBERException {
return template.decode(istream);
}
/**
* Decodes a SET OF
with an implicit tag from its BER
* encoding.
*/
@Override
public ASN1Value decode(Tag implicitTag, InputStream istream)
throws IOException, InvalidBERException {
return template.decode(implicitTag, istream);
}
}
// Test driver for SET
public static void main(String[] args) {
try {
if (args.length > 0) {
Template t = new SET.Template();
t.addElement(new Tag(0), new INTEGER.Template());
t.addElement(new Tag(3), new INTEGER.Template());
t.addOptionalElement(new Tag(4), new INTEGER.Template());
t.addElement(new Tag(5), new INTEGER.Template(), new INTEGER(67));
t.addElement(new Tag(29), new BOOLEAN.Template());
t.addElement(new Tag(30), new BOOLEAN.Template(), new BOOLEAN(false));
t.addElement(new Tag(1), new INTEGER.Template());
t.addElement(new Tag(2), new INTEGER.Template());
SET st;
FileInputStream fin = new FileInputStream(args[0]);
try (BufferedInputStream is = new BufferedInputStream(fin)) {
st = (SET) t.decode(is);
}
for (int i = 0; i < st.size(); i++) {
ASN1Value v = st.elementAt(i);
if (v instanceof INTEGER) {
INTEGER in = (INTEGER) st.elementAt(i);
System.out.println("INTEGER: " + in);
} else if (v instanceof BOOLEAN) {
BOOLEAN bo = (BOOLEAN) st.elementAt(i);
System.out.println("BOOLEAN: " + bo);
} else {
System.out.println("Unknown value");
}
}
} else {
SET s = new SET();
s.addElement(new Tag(0), new INTEGER(255));
s.addElement(new Tag(29), new BOOLEAN(true));
s.addElement(new Tag(1), new INTEGER(-322));
s.addElement(new Tag(2), new INTEGER(0));
s.addElement(new Tag(3), new INTEGER("623423948273"));
s.encode(System.out);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/asn1/Tag.java 0000664 0000000 0000000 00000012062 14565430767 0023165 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.asn1;
/**
* Represents an ASN.1 Tag. A tag consists of a class and a number.
*/
public class Tag {
private long num;
/**
* @return The tag number.
*/
public long getNum() {
return num;
}
private Class tClass;
/**
* @return The tag class.
*/
public Class getTagClass() {
return tClass;
}
/**
* A tag class.
*/
public static final Class UNIVERSAL = Class.UNIVERSAL;
/**
* A tag class.
*/
public static final Class APPLICATION = Class.APPLICATION;
/**
* A tag class.
*/
public static final Class CONTEXT_SPECIFIC = Class.CONTEXT_SPECIFIC;
/**
* A tag class.
*/
public static final Class PRIVATE = Class.PRIVATE;
/**
* The end-of-contents marker for indefinite length encoding.
* It is encoded the same as an ASN.1 header whose tag is [UNIVERSAL 0].
*/
public static final Tag END_OF_CONTENTS = new Tag(UNIVERSAL, 0);
/**
* An alias for END_OF_CONTENTS.
*/
public static final Tag EOC = END_OF_CONTENTS;
/**
* Creates a tag with the given class and number.
*
* @param clazz The class of the tag.
* @param num The tag number.
*/
public Tag(Class clazz, long num) {
tClass = clazz;
this.num = num;
}
/**
* Creates a CONTEXT-SPECIFIC tag with the given tag number.
*
* @param num The tag number.
*/
public Tag(long num) {
this(Class.CONTEXT_SPECIFIC, num);
}
///////////////////////////////////////////////////////////////////////
// Tag Instances
//
// Since grabbing a context-specific tag is a very common operation,
// let's make singletons of the most frequently used tags.
///////////////////////////////////////////////////////////////////////
private static final int numTagInstances = 10;
private static Tag tagInstances[] = new Tag[numTagInstances];
static {
for (int i = 0; i < numTagInstances; i++) {
tagInstances[i] = new Tag(i);
}
}
/**
* Returns an instance of a context-specific tag with the given number.
* The returned instance may be singleton. It is usually more efficient to
* call this method than create your own context-specific tag.
*
* @param num Number.
* @return Tag.
*/
public static Tag get(long num) {
if (num >= 0 && num < numTagInstances) {
return tagInstances[(int) num];
} else {
return new Tag(num);
}
}
@Override
public int hashCode() {
return (tClass.toInt() * 131) + (int) num;
}
/**
* Compares two tags for equality. Tags are equal if they have
* the same class and tag number.
*
* @param obj Tag.
* @return True if equal.
*/
@Override
public boolean equals(Object obj) {
if (obj == null) {
return false;
}
if (!(obj instanceof Tag)) {
return false;
}
Tag t = (Tag) obj;
if (num == t.num && tClass == t.tClass) {
return true;
} else {
return false;
}
}
/**
* Returns a String representation of the tag. For example, a tag
* whose class was UNIVERSAL and whose number was 16 would return
* "UNIVERSAL 16".
*/
@Override
public String toString() {
return tClass + " " + num;
}
/**
* An enumeration of the ASN.1 tag classes.
*/
public static class Class {
private Class() {
}
private Class(int enc, String name) {
encoding = enc;
this.name = name;
}
private int encoding;
private String name;
public static final Class UNIVERSAL = new Class(0, "UNIVERSAL");
public static final Class APPLICATION = new Class(1, "APPLICATION");
public static final Class CONTEXT_SPECIFIC = new Class(2, "CONTEXT-SPECIFIC");
public static final Class PRIVATE = new Class(3, "PRIVATE");
public int toInt() {
return encoding;
}
@Override
public String toString() {
return name;
}
/**
* @param i Tag encoding.
* @return Tag class.
* @exception InvalidBERException If the given int does not correspond
* to any tag class.
*/
public static Class fromInt(int i) throws InvalidBERException {
if (i == 0) {
return UNIVERSAL;
} else if (i == 1) {
return APPLICATION;
} else if (i == 2) {
return CONTEXT_SPECIFIC;
} else if (i == 3) {
return PRIVATE;
} else {
throw new InvalidBERException("Invalid tag class: " + i);
}
}
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/asn1/TeletexString.java 0000664 0000000 0000000 00000005430 14565430767 0025254 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.asn1;
import java.io.CharConversionException;
/**
* The ASN.1 type TeletexString.
*/
public class TeletexString extends CharacterString {
public static final Tag TAG = new Tag(Tag.UNIVERSAL, 20);
@Override
public Tag getTag() {
return TAG;
}
public TeletexString(char[] chars) throws CharConversionException {
super(chars);
}
public TeletexString(String s) throws CharConversionException {
super(s);
}
@Override
CharConverter getCharConverter() {
return new TeletexConverter();
}
/**
* Returns a singleton instance of the decoding template for this class.
*
* @return Template.
*/
public static Template getTemplate() {
return templateInstance;
}
private static final Template templateInstance = new Template();
// nested class
public static class Template
extends CharacterString.Template {
@Override
protected Tag getTag() {
return TAG;
}
@Override
public boolean tagMatch(Tag tag) {
return TAG.equals(tag);
}
@Override
protected CharConverter getCharConverter() {
return new TeletexConverter();
}
@Override
protected CharacterString generateInstance(char[] bytes)
throws CharConversionException {
return new TeletexString(bytes);
}
@Override
protected String typeName() {
return "TeletexString";
}
} // end of Template
private static class TeletexConverter implements CharConverter {
@Override
public char[] byteToChar(byte[] bytes, int offset, int len)
throws CharConversionException {
char[] chars = new char[len];
int b;
int c;
for (b = offset, c = 0; c < len; b++, c++) {
chars[c] = (char) (bytes[b] & 0xff);
}
return chars;
}
@Override
public byte[] charToByte(char[] chars, int offset, int len)
throws CharConversionException {
byte[] bytes = new byte[len];
int b;
int c;
for (b = 0, c = offset; b < len; b++, c++) {
if ((chars[c] & 0xff00) != 0) {
throw new CharConversionException("Invalid character for" +
" TeletexString");
}
bytes[b] = (byte) (chars[c] & 0xff);
}
return bytes;
}
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/asn1/TimeBase.java 0000664 0000000 0000000 00000022544 14565430767 0024151 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.asn1;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Calendar;
import java.util.Date;
import java.util.TimeZone;
public abstract class TimeBase implements ASN1Value {
public static final Form FORM = Form.PRIMITIVE;
@Override
abstract public Tag getTag();
private Date date;
public Date toDate() {
return date;
}
abstract protected boolean isUTC();
public TimeBase(Date date) {
this.date = date;
}
@Override
public void encode(OutputStream ostream) throws IOException {
encode(getTag(), ostream);
}
/**
* Write the DER-encoding of this TimeBase.
*/
@Override
public void encode(Tag implicit, OutputStream ostream) throws IOException {
if (isUTC()) {
// length will always be 13
(new ASN1Header(implicit, FORM, 13)).encode(ostream);
} else {
// length will always be 15
(new ASN1Header(implicit, FORM, 15)).encode(ostream);
}
int i = 0, val;
// DER-encoding mandates GMT time zone
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
cal.setTime(date);
if (isUTC()) {
val = cal.get(Calendar.YEAR);
ostream.write(((val % 100) / 10) + '0');
ostream.write((val % 10) + '0');
} else {
val = cal.get(Calendar.YEAR);
ostream.write(((val % 10000) / 1000) + '0');
ostream.write(((val % 1000) / 100) + '0');
ostream.write(((val % 100) / 10) + '0');
ostream.write((val % 10) + '0');
}
val = cal.get(Calendar.MONTH) + 1;
assert (val >= 1 && val <= 12);
ostream.write((val / 10) + '0');
ostream.write((val % 10) + '0');
val = cal.get(Calendar.DAY_OF_MONTH);
assert (val >= 1 && val <= 31);
ostream.write((val / 10) + '0');
ostream.write((val % 10) + '0');
val = cal.get(Calendar.HOUR_OF_DAY);
assert (val >= 0 && val <= 23);
ostream.write((val / 10) + '0');
ostream.write((val % 10) + '0');
val = cal.get(Calendar.MINUTE);
assert (val >= 0 && val <= 59);
ostream.write((val / 10) + '0');
ostream.write((val % 10) + '0');
val = cal.get(Calendar.SECOND);
assert (val >= 0 && val <= 59);
ostream.write((val / 10) + '0');
ostream.write((val % 10) + '0');
ostream.write('Z');
}
public abstract static class Template {
protected abstract boolean isUTC();
protected abstract Tag getTag();
protected abstract TimeBase generateInstance(Date date);
public boolean tagMatch(Tag tag) {
return getTag().equals(tag);
}
public ASN1Value decode(InputStream istream)
throws IOException, InvalidBERException {
return decode(getTag(), istream);
}
public ASN1Value decode(Tag implicitTag, InputStream istream)
throws IOException, InvalidBERException {
PrintableString.Template pst = new PrintableString.Template();
PrintableString ps = (PrintableString) pst.decode(implicitTag, istream);
char[] chars = ps.toCharArray();
int i = 0;
int year, month, day, hour, minute, second, hourOff, minOff;
//////////////////////////////////////////
// Get year
//
if (isUTC()) {
checkBounds(i, 2, chars.length);
year = (chars[i] - '0') * 10;
year += chars[i + 1] - '0';
// Y2K HACK!!!!! But this is what the spec says to do.
// The range is 1970 to 2069
if (year < 70) {
year += 2000;
} else {
year += 1900;
}
i += 2;
} else {
checkBounds(i, 4, chars.length);
year = (chars[i] - '0') * 1000;
year += (chars[i + 1] - '0') * 100;
year += (chars[i + 2] - '0') * 10;
year += (chars[i + 3] - '0');
checkRange(year, 0, 9999, "year");
i += 4;
}
//////////////////////////////////////////
// get month
//
month = 0;
checkBounds(i, 2, chars.length);
month = (chars[i] - '0') * 10;
month += chars[i + 1] - '0';
checkRange(month, 1, 12, "month");
month--; // Java months start at 0
i += 2;
//////////////////////////////////////////
// get day
//
checkBounds(i, 2, chars.length);
day = (chars[i] - '0') * 10;
day += chars[i + 1] - '0';
checkRange(day, 1, 31, "day");
i += 2;
//////////////////////////////////////////
// get hour
//
checkBounds(i, 2, chars.length);
hour = (chars[i] - '0') * 10;
hour += chars[i + 1] - '0';
checkRange(hour, 0, 23, "hour");
i += 2;
//////////////////////////////////////////
// get minute
//
checkBounds(i, 2, chars.length);
minute = (chars[i] - '0') * 10;
minute += chars[i + 1] - '0';
checkRange(minute, 0, 59, "minute");
i += 2;
//////////////////////////////////////////
// get second, if it's there
//
if (i < chars.length && chars[i] >= '0' && chars[i] <= '9') {
checkBounds(i, 2, chars.length);
second = (chars[i] - '0') * 10;
second += chars[i + 1] - '0';
checkRange(second, 0, 59, "second");
i += 2;
} else {
second = 0;
}
//////////////////////////////////////////
// Skip milliseconds for GeneralizedTime. There are no
// milliseconds in UTCTime.
//
if (!isUTC()) {
while (i < chars.length &&
chars[i] != '+' &&
chars[i] != '-' &&
chars[i] != 'Z') {
i++;
}
}
//////////////////////////////////////////
// get time zone
//
TimeZone tz;
if (i < chars.length) {
checkBounds(i, 1, chars.length);
if (chars[i] == '+' || chars[i] == '-') {
checkBounds(i + 1, 4, chars.length);
hourOff = (chars[i + 1] - '0') * 10;
hourOff += chars[i + 2] - '0';
minOff = (chars[i + 3] - '0') * 10;
minOff += chars[i + 4] - '0';
checkRange(hourOff, 0, 23, "hour offset");
checkRange(minOff, 0, 59, "minute offset");
if (chars[i] == '-') {
hourOff = -hourOff;
minOff = -minOff;
}
i += 5;
tz = (TimeZone) TimeZone.getTimeZone("GMT").clone();
tz.setRawOffset(((hourOff * 60) + minOff) * 60 * 1000);
} else if (chars[i] == 'Z') {
i += 1;
hourOff = minOff = 0;
tz = (TimeZone) TimeZone.getTimeZone("GMT").clone();
} else {
throw new InvalidBERException("Invalid character " +
chars[i]);
}
} else {
if (isUTC()) {
// Only UTC requires timezone
throw new InvalidBERException("no timezone specified for" +
" UTCTime");
}
// No timezone specified, use local time.
// This is generally a bad idea, because who knows what the
// local timezone is? But the spec allows it.
tz = TimeZone.getDefault();
}
// make sure we ate all the characters, there were no stragglers
// at the end
if (i != chars.length) {
throw new InvalidBERException("Extra characters at end");
}
// Create a calendar object from the date and time zone.
Calendar cal = Calendar.getInstance(tz);
cal.set(year, month, day, hour, minute, second);
return generateInstance(cal.getTime());
}
private static void checkRange(int val, int low, int high, String field)
throws InvalidBERException {
if (val < low || val > high) {
throw new InvalidBERException("Invalid " + field);
}
}
private static void checkBounds(int index, int increment, int bound)
throws InvalidBERException {
if (index + increment > bound) {
throw new InvalidBERException("Too few characters in " +
"TimeBase");
}
}
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/asn1/UTCTime.java 0000664 0000000 0000000 00000002346 14565430767 0023730 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.asn1;
import java.util.Date;
public class UTCTime extends TimeBase {
public static final Tag TAG = new Tag(Tag.UNIVERSAL, 23);
@Override
public Tag getTag() {
return TAG;
}
public UTCTime(Date date) {
super(date);
}
@Override
protected boolean isUTC() {
return true;
}
private static final UTCTime.Template templateInstance = new UTCTime.Template();
public static UTCTime.Template getTemplate() {
return templateInstance;
}
public static class Template extends TimeBase.Template
implements ASN1Template {
@Override
protected Tag getTag() {
return TAG;
}
@Override
public boolean tagMatch(Tag tag) {
return TAG.equals(tag);
}
@Override
protected boolean isUTC() {
return true;
}
@Override
protected TimeBase generateInstance(Date date) {
return new UTCTime(date);
}
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/asn1/UTF8String.java 0000664 0000000 0000000 00000005655 14565430767 0024401 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.asn1;
import java.io.CharConversionException;
import java.io.UnsupportedEncodingException;
public class UTF8String extends CharacterString {
public UTF8String(char[] chars) throws CharConversionException {
super(chars);
}
public UTF8String(String s) throws CharConversionException {
super(s);
}
@Override
CharConverter getCharConverter() {
return new UTF8Converter();
}
public static final Tag TAG = new Tag(Tag.UNIVERSAL, 12);
public static final Form FORM = Form.PRIMITIVE;
@Override
public Tag getTag() {
return TAG;
}
private static final Template templateInstance = new Template();
/**
* Returns a singleton instance of UTF8String.Template. This is more
* efficient than creating a new UTF8String.Template.
*
* @return Template.
*/
public static Template getTemplate() {
return templateInstance;
}
// nested class
public static class Template
extends CharacterString.Template {
@Override
protected Tag getTag() {
return TAG;
}
@Override
public boolean tagMatch(Tag tag) {
return TAG.equals(tag);
}
@Override
protected CharConverter getCharConverter() {
return new UTF8Converter();
}
@Override
protected CharacterString generateInstance(char[] chars)
throws CharConversionException {
return new UTF8String(chars);
}
@Override
protected String typeName() {
return "UTF8String";
}
}
private static class UTF8Converter implements CharConverter {
@Override
public char[] byteToChar(byte[] bytes, int offset, int len)
throws CharConversionException {
try {
String s = new String(bytes, offset, len, "UTF8");
return s.toCharArray();
} catch (UnsupportedEncodingException e) {
String err = "Unable to find UTF8 encoding mechanism";
throw (CharConversionException) new CharConversionException(err).initCause(e);
}
}
@Override
public byte[] charToByte(char[] chars, int offset, int len)
throws CharConversionException {
try {
String s = new String(chars, offset, len);
return s.getBytes("UTF8");
} catch (UnsupportedEncodingException e) {
String err = "Unable to find UTF8 encoding mechanism";
throw (CharConversionException) new CharConversionException(err).initCause(e);
}
}
} // end of char converter
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/asn1/UniversalString.java 0000664 0000000 0000000 00000015501 14565430767 0025612 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.asn1;
import java.io.ByteArrayOutputStream;
import java.io.CharArrayWriter;
import java.io.CharConversionException;
/**
* A UCS4 string.
*/
public class UniversalString extends CharacterString {
public static final Tag TAG = new Tag(Tag.UNIVERSAL, 28);
@Override
public Tag getTag() {
return TAG;
}
public UniversalString(char[] chars) throws CharConversionException {
super(chars);
}
public UniversalString(String s) throws CharConversionException {
super(s);
}
@Override
CharConverter getCharConverter() {
return new UniversalConverter();
}
/**
* Returns a singleton instance of the decoding template for this class.
*
* @return Template.
*/
public static Template getTemplate() {
return templateInstance;
}
private static final Template templateInstance = new Template();
// nested class
public static class Template
extends CharacterString.Template {
@Override
protected Tag getTag() {
return TAG;
}
@Override
public boolean tagMatch(Tag tag) {
return TAG.equals(tag);
}
@Override
protected CharConverter getCharConverter() {
return new UniversalConverter();
}
@Override
protected CharacterString generateInstance(char[] chars)
throws CharConversionException {
return new UniversalString(chars);
}
@Override
protected String typeName() {
return "UniversalString";
}
} // end of Template
/**
* A class for converting between Unicode and UCS4.
*/
private static class UniversalConverter implements CharConverter {
// This is the maximum a UCS4 character can be if it has
// straight Unicode inside it.
public static final int MAX_UNICODE = 0x0000ffff;
// This is the maximum a UCS4 character can be if it is UTF-16
// encoded. UTF-16 encoding allows UCS4 chars to be stored across
// two Unicode chars.
public static final int MAX_UTF16 = 0x0010ffff;
// This Unicode character is used to represent an unknown character
// in some other encoding. We use it for UCS4 characters that
// are not a part of normal Unicode and also cannot be encoded
// across two Unicode chars with UTF-16.
public static final char REPLACEMENT_CHAR = 0xfffd;
// This is the base for UCS4 characters that can be mapped with UTF16.
public static final int UTF16_BASE = 0x00100000;
// In UTF16 encoding, each Unicode character has 10 bits of
// information.
public static final int HALF_SHIFT = 10;
// The lowest 10 bits
public static final int HALF_MASK = 0x3ff;
public static final int UTF16_HIGH_START = 0xd800;
public static final int UTF16_HIGH_END = 0xdcff;
public static final int UTF16_LOW_START = 0xdc00;
public static final int UTF16_LOW_END = 0xdfff;
/**
* Turns big-endian UCS4 characters into Unicode Java characters
*/
@Override
public char[] byteToChar(byte[] bytes, int offset, int len)
throws CharConversionException {
// Each UCS4 character is 4 bytes. Most UCS4 characters will
// map to one Unicode character. The exception is UTF-16
// characters, which map to two Unicode characters.
CharArrayWriter out = new CharArrayWriter(len / 4);
int end = offset + len;
while (offset < end) {
// eat 4 bytes and make a UCS4 char
if (end - offset < 4) {
throw new CharConversionException("input exhausted");
}
int ucs4 = (bytes[offset++] & 0xff) << 24;
ucs4 += (bytes[offset++] & 0xff) << 16;
ucs4 += (bytes[offset++] & 0xff) << 8;
ucs4 += bytes[offset++] & 0xff;
// convert UCS4 to Unicode
if (ucs4 <= MAX_UNICODE) {
// Unicode is a subset of UCS4, and this char is
// in the common subset. Just chop off the unused top
// two bytes.
out.write(ucs4 & 0xffff);
} else if (ucs4 <= MAX_UTF16) {
// This UCS4 char is not in Unicode, but can be encoded
// into two Unicode chars using UTF16.
ucs4 -= UTF16_BASE;
out.write((ucs4 >>> HALF_SHIFT) + UTF16_HIGH_START);
out.write((ucs4 & HALF_MASK) + UTF16_LOW_START);
} else {
// This character is not in Unicode or UTF16. We can't
// provide a suitable translation, so use the Unicode
// replacement char.
out.write(REPLACEMENT_CHAR);
}
}
return out.toCharArray();
}
// Convert Unicode chars to UCS4 chars
@Override
public byte[] charToByte(char[] chars, int offset, int len)
throws CharConversionException {
ByteArrayOutputStream out = new ByteArrayOutputStream(len * 4);
int end = offset + len;
while (offset < end) {
char c = chars[offset++];
int ucs4;
if (c >= UTF16_HIGH_START && c <= UTF16_HIGH_END) {
// This is the beginning of a UTF16 char
if (offset == end) {
throw new CharConversionException("input exhausted");
}
char low = chars[offset++];
// make sure the next char is the low half of a UTF16 char
if (low < UTF16_LOW_START || low > UTF16_LOW_END) {
throw new CharConversionException("UTF16 high " +
"character not followed by a UTF16 low character");
}
ucs4 = UTF16_BASE;
ucs4 += (c - UTF16_HIGH_START) << HALF_SHIFT;
ucs4 += low - UTF16_LOW_START;
} else {
// this is a normal Unicode char
ucs4 = (c & 0x0000ffff);
}
out.write((ucs4 & 0xff000000) >>> 24);
out.write((ucs4 & 0x00ff0000) >>> 16);
out.write((ucs4 & 0x0000ff00) >>> 8);
out.write((ucs4 & 0x000000ff));
}
return out.toByteArray();
}
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/asn1/package.html 0000664 0000000 0000000 00000000557 14565430767 0024076 0 ustar 00root root 0000000 0000000
org.mozilla.jss.asn1
ASN.1 structures, BER decoding, and DER encoding.
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/ 0000775 0000000 0000000 00000000000 14565430767 0022264 5 ustar 00root root 0000000 0000000 jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/Algorithm.java 0000664 0000000 0000000 00000025661 14565430767 0025067 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.crypto;
import java.security.NoSuchAlgorithmException;
import org.mozilla.jss.asn1.OBJECT_IDENTIFIER;
/**
* Represents a cryptographic algorithm.
*
* @see EncryptionAlgorithm
* @see SignatureAlgorithm
*/
public class Algorithm {
/**
* @param oidIndex Index of the oid that this algorithm represents.
* @param name A String representation of the Algorithm.
*/
protected Algorithm(int oidIndex, String name) {
this.oidIndex = oidIndex;
this.name = name;
}
/**
* @param oidIndex Index of the oid that this algorithm represents.
* @param name A String representation of the Algorithm.
* @param oid The object identifier for this Algorithm.
*/
protected Algorithm(int oidIndex, String name, OBJECT_IDENTIFIER oid) {
this(oidIndex, name);
this.oid = oid;
}
protected Algorithm(int oidIndex, String name, OBJECT_IDENTIFIER oid,
Class> paramClass) {
this(oidIndex, name, oid);
if (paramClass == null) {
this.parameterClasses = new Class[0];
} else {
this.parameterClasses = new Class[1];
this.parameterClasses[0] = paramClass;
}
}
protected Algorithm(int oidIndex, String name, OBJECT_IDENTIFIER oid,
Class>[] paramClasses) {
this(oidIndex, name, oid);
if (paramClasses != null) {
this.parameterClasses = paramClasses;
}
}
/**
* Returns a String representation of the algorithm.
*/
@Override
public String toString() {
return name;
}
/**
* @return The object identifier for this algorithm.
* @exception NoSuchAlgorithmException If no OID is registered for this
* algorithm.
*/
public OBJECT_IDENTIFIER toOID() throws NoSuchAlgorithmException {
if (oid == null) {
throw new NoSuchAlgorithmException();
}
return oid;
}
/**
* The type of parameter that this algorithm expects. Returns
* null
if this algorithm does not take any parameters.
* If the algorithm can accept more than one type of parameter,
* this method returns only one of them. It is better to call
* getParameterClasses()
.
*
* @return Parameter type.
* @deprecated Call getParameterClasses()
instead.
*/
@Deprecated
public Class> getParameterClass() {
return parameterClasses.length == 0 ? null : parameterClasses[0];
}
/**
* The types of parameter that this algorithm expects. Returns
* null
if this algorithm does not take any parameters.
*
* @return Parameter types.
*/
public Class>[] getParameterClasses() {
return parameterClasses.clone();
}
/**
* Validates if the given Object can be used as a parameter
* for this algorithm.
*
* If null
is passed in, this method will return true
* if this algorithm takes no parameters, and false
* if this algorithm does take parameters.
*
* @param o Object.
* @return Returns true
if the given Object can be used as a parameter.
*/
public boolean isValidParameterObject(Object o) {
if (o == null) {
return (parameterClasses.length == 0);
}
if (parameterClasses.length == 0) {
return false;
}
Class> c = o.getClass();
for (int i = 0; i < parameterClasses.length; ++i) {
if (c.equals(parameterClasses[i])) {
return true;
}
}
return false;
}
public PKCS11Algorithm getEnum() {
return PKCS11Algorithm.valueOfIndex(this.oidIndex);
}
/**
* Index into the SECOidTag array in Algorithm.c.
*/
protected int oidIndex;
String name;
protected OBJECT_IDENTIFIER oid;
private Class>[] parameterClasses = new Class[0];
//////////////////////////////////////////////////////////////
// Algorithm OIDs
//////////////////////////////////////////////////////////////
static final OBJECT_IDENTIFIER ANSI_X9_ALGORITHM = new OBJECT_IDENTIFIER(new long[] { 1, 2, 840, 10040, 4 });
static final OBJECT_IDENTIFIER ANSI_X962_OID = new OBJECT_IDENTIFIER(new long[] { 1, 2, 840, 10045 });
// Algorithm indices. These must be kept in sync with the
// algorithm array in Algorithm.c. Any PKCS11 Algorithms must be added
// to the org.mozilla.jss.crypto.PKCS11Algorithm enum.
protected static final int SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION = 0;
protected static final int SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION = 1;
@Deprecated(since="5.0.1", forRemoval=true)
protected static final int SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION = 2;
@Deprecated(since="5.0.1", forRemoval=true)
protected static final int SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST = 3;
protected static final int SEC_OID_PKCS1_RSA_ENCRYPTION = 4;
protected static final int CKM_RSA_PKCS_KEY_PAIR_GEN = 5;
protected static final int CKM_DSA_KEY_PAIR_GEN = 6;
protected static final int SEC_OID_ANSIX9_DSA_SIGNATURE = 7;
protected static final int SEC_OID_RC4 = 8;
protected static final int SEC_OID_DES_ECB = 9;
protected static final int SEC_OID_DES_CBC = 10;
protected static final int CKM_DES_CBC_PAD = 11;
protected static final int CKM_DES3_ECB = 12;
protected static final int SEC_OID_DES_EDE3_CBC = 13;
protected static final int CKM_DES3_CBC_PAD = 14;
protected static final int CKM_DES_KEY_GEN = 15;
protected static final int CKM_DES3_KEY_GEN = 16;
protected static final int CKM_RC4_KEY_GEN = 17;
protected static final int SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC = 18;
protected static final int SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC = 19;
@Deprecated(since="5.0.1", forRemoval=true)
protected static final int SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC = 20;
@Deprecated(since="5.0.1", forRemoval=true)
protected static final int SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4 = 21;
@Deprecated(since="5.0.1", forRemoval=true)
protected static final int SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4 = 22;
@Deprecated(since="5.0.1", forRemoval=true)
protected static final int SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC = 23;
protected static final int SEC_OID_MD2 = 24;
protected static final int SEC_OID_MD5 = 25;
@Deprecated(since="5.0.1", forRemoval=true)
protected static final int SEC_OID_SHA1 = 26;
@Deprecated(since="5.0.1", forRemoval=true)
protected static final int CKM_SHA_1_HMAC = 27;
@Deprecated(since="5.0.1", forRemoval=true)
protected static final int SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC = 28;
@Deprecated(since="5.0.1", forRemoval=true)
protected static final int SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC = 29;
protected static final int SEC_OID_RC2_CBC = 30;
@Deprecated(since="5.0.1", forRemoval=true)
protected static final int CKM_PBA_SHA1_WITH_SHA1_HMAC = 31;
// AES
protected static final int CKM_AES_KEY_GEN = 32;
protected static final int CKM_AES_ECB = 33;
protected static final int CKM_AES_CBC = 34;
protected static final int CKM_AES_CBC_PAD = 35;
protected static final int CKM_RC2_CBC_PAD = 36;
protected static final int CKM_RC2_KEY_GEN = 37;
//FIPS 180-2
protected static final int SEC_OID_SHA256 = 38;
protected static final int SEC_OID_SHA384 = 39;
protected static final int SEC_OID_SHA512 = 40;
protected static final int SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION = 41;
protected static final int SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION = 42;
protected static final int SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION = 43;
protected static final int SEC_OID_ANSIX962_EC_PUBLIC_KEY = 44;
@Deprecated(since="5.0.1", forRemoval=true)
protected static final int SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE = 45;
protected static final int CKM_EC_KEY_PAIR_GEN = 46;
protected static final int SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE = 47;
protected static final int SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE = 48;
protected static final int SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE = 49;
protected static final int SEC_OID_HMAC_SHA256 = 50;
protected static final int SEC_OID_HMAC_SHA384 = 51;
protected static final int SEC_OID_HMAC_SHA512 = 52;
//PKCS5 V2
protected static final int SEC_OID_PKCS5_PBKDF2 = 53;
protected static final int SEC_OID_PKCS5_PBES2 = 54;
protected static final int SEC_OID_PKCS5_PBMAC1 = 55;
protected static final int SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST = 56;
// NSS AES KeyWrap
protected static final int CKM_NSS_AES_KEY_WRAP = 57;
protected static final int CKM_NSS_AES_KEY_WRAP_PAD = 58;
// AES Encryption Algorithms
protected static final int SEC_OID_AES_128_ECB = 59;
protected static final int SEC_OID_AES_128_CBC = 60;
protected static final int SEC_OID_AES_192_ECB = 61;
protected static final int SEC_OID_AES_192_CBC = 62;
protected static final int SEC_OID_AES_256_ECB = 63;
protected static final int SEC_OID_AES_256_CBC = 64;
// PKCS#11 AES KeyWrap
// These underlying defs are currently different from the NSS AES KeyWrap
protected static final int CKM_AES_KEY_WRAP = 65;
protected static final int CKM_AES_KEY_WRAP_PAD = 66;
// PKCS#11 SHA2 HMAC
protected static final int CKM_SHA256_HMAC = 67;
protected static final int CKM_SHA384_HMAC = 68;
protected static final int CKM_SHA512_HMAC = 69;
// PKCS#11 AES-CMAC
protected static final int CKM_AES_CMAC = 70;
// Generic Secret
protected static final int CKM_GENERIC_SECRET_KEY_GEN = 71;
// PKCS#11 NIST SP800-108 KBKDFs (including NSS variants)
protected static final int CKM_SP800_108_COUNTER_KDF = 72;
protected static final int CKM_SP800_108_FEEDBACK_KDF = 73;
protected static final int CKM_SP800_108_DOUBLE_PIPELINE_KDF = 74;
protected static final int CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA = 75;
protected static final int CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA = 76;
protected static final int CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA = 77;
// RSA-PSS
protected static final int SEC_OID_PKCS1_RSA_PSS_SIGNATURE = 78;
// RSA-OAEP
protected static final int CKM_RSA_PKCS_OAEP = 79;
// CKM_AES_KEY_WRAP_KWP for HSM support
protected static final int CKM_AES_KEY_WRAP_KWP = 80;
protected static final int SEC_OID_AES_128_KEY_WRAP_KWP = 81;
protected static final int SEC_OID_AES_192_KEY_WRAP_KWP = 82;
protected static final int SEC_OID_AES_256_KEY_WRAP_KWP = 83;
protected static final int SEC_OID_HMAC_SHA1 = 84;
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/AlreadyInitializedException.java 0000664 0000000 0000000 00000001631 14565430767 0030556 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.crypto;
/**
* This exception is thrown if an initialization operation
* is attempted on something that is already initialized.
*/
public class AlreadyInitializedException extends java.lang.Exception {
private static final long serialVersionUID = 1L;
public AlreadyInitializedException() {}
public AlreadyInitializedException(String mesg) {
super(mesg);
}
public AlreadyInitializedException(String mesg, Throwable cause) {
super(mesg, cause);
}
public AlreadyInitializedException(String mesg, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(mesg, cause, enableSuppression, writableStackTrace);
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/BadPaddingException.java 0000664 0000000 0000000 00000001076 14565430767 0026767 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.crypto;
/**
* @deprecated Use javax.crypto.BadPaddingException.
*/
@Deprecated
public class BadPaddingException extends javax.crypto.BadPaddingException {
private static final long serialVersionUID = 1L;
public BadPaddingException() {
super();
}
public BadPaddingException(String mesg) {
super(mesg);
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/CMACAlgorithm.java 0000664 0000000 0000000 00000004671 14565430767 0025511 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.crypto;
import java.security.NoSuchAlgorithmException;
import java.util.Hashtable;
import org.mozilla.jss.asn1.OBJECT_IDENTIFIER;
/**
* Algorithms for performing CMACs. These can be used to create
* MessageDigests.
*/
public class CMACAlgorithm extends DigestAlgorithm {
protected CMACAlgorithm(int oidIndex, String name, OBJECT_IDENTIFIER oid,
int outputSize) {
super(oidIndex, name, oid, outputSize);
if (oid != null && oidMap.get(oid) == null) {
oidMap.put(oid, this);
}
}
///////////////////////////////////////////////////////////////////////
// OID mapping
///////////////////////////////////////////////////////////////////////
private static Hashtable oidMap = new Hashtable<>();
/**
* Looks up the CMAC algorithm with the given OID.
*
* @param oid OID.
* @return CMAC algorithm.
* @exception NoSuchAlgorithmException If no registered CMAC algorithm
* has the given OID.
*/
public static CMACAlgorithm fromOID(OBJECT_IDENTIFIER oid)
throws NoSuchAlgorithmException
{
CMACAlgorithm alg = oidMap.get(oid);
if (alg == null) {
throw new NoSuchAlgorithmException("No such algorithm for OID: " + oid);
}
return alg;
}
/**
* CMAC AES-X. This is a Message Authentication Code that uses a
* symmetric key together with the AES cipher to create a form of
* signature.
*
* Note that we pass null for the OID here: neither NIST nor any other
* standards body has defined an OID for use with CMAC. Since we use
* a PKCS#11 backend and NSS doesn't otherwise define CMAC based on a
* SEC OID, we don't strictly need one.
*
* We've left the fromOID code (and oid parameter in the constructor) as
* other projects use them for HMACAlgorith. At such time as an OID is
* defined, it can be added here.
*/
public static final CMACAlgorithm AES = new CMACAlgorithm(CKM_AES_CMAC, "AES-CMAC", null, 16);
public static final CMACAlgorithm AES128 = AES;
public static final CMACAlgorithm AES192 = AES;
public static final CMACAlgorithm AES256 = AES;
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/Cipher.java 0000664 0000000 0000000 00000016751 14565430767 0024353 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.crypto;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.spec.AlgorithmParameterSpec;
import javax.crypto.BadPaddingException;
/**
* A context for performing symmetric encryption and decryption.
* First, the context must be initialized. Then, it can be updated
* with input through zero or more calls to update
. Finally,
* doFinal
is called to finalize the operation. Note that
* it is not necessary to call update
if all of the data is
* available at once. In this case, all of the input can be processed with one
* call to doFinal
.
*/
public abstract class Cipher {
// Note: Cipher can't extend javax.crypto.Cipher because it is part of the
// provider mechanism. In particular, it isn't an abstract class, many of
// the methods are marked final, and it expects to instantiate a CipherSpi
// class instead of be directly created like things which override our
// Cipher class expect (e.g., PK11Cipher). This is why JSSCipherSpi exists.
/**
* Initializes a encryption context with a symmetric key.
*/
public abstract void initEncrypt(SymmetricKey key)
throws InvalidKeyException, InvalidAlgorithmParameterException,
TokenException;
/**
* Initializes a decryption context with a symmetric key.
*/
public abstract void initDecrypt(SymmetricKey key)
throws InvalidKeyException, InvalidAlgorithmParameterException,
TokenException;
/**
* Initializes an encryption context with a symmetric key and
* algorithm parameters.
*/
public abstract void
initEncrypt(SymmetricKey key, AlgorithmParameterSpec parameters)
throws InvalidKeyException, InvalidAlgorithmParameterException,
TokenException;
/**
* Initializes a decryption context with a symmetric key and
* algorithm parameters.
*/
public abstract void
initDecrypt(SymmetricKey key, AlgorithmParameterSpec parameters)
throws InvalidKeyException, InvalidAlgorithmParameterException,
TokenException;
/**
* Updates the encryption context with additional input.
* @param bytes Bytes of plaintext (if encrypting) or ciphertext (if
* decrypting).
* @return Bytes of ciphertext (if encrypting) or plaintext (if decrypting).
*/
public abstract byte[] update(byte[] bytes)
throws IllegalStateException, TokenException;
/**
* Updates the encryption context with additional plaintext.
* @param bytes Bytes of plaintext (if encrypting) or ciphertext (if
* decrypting).
* @param offset The index in bytes
at which to begin reading.
* @param length The number of bytes from bytes
to read.
* @return Bytes of ciphertext (if encrypting) or plaintext (if decrypting).
*/
public abstract byte[] update(byte[] bytes, int offset, int length)
throws IllegalStateException, TokenException;
/**
* Completes an cipher operation. This can be called directly after
* the context is initialized, or update
may be called
* any number of times before calling final
.
* @param bytes Bytes of plaintext (if encrypting) or ciphertext (if
* decrypting).
* @return The last of the output.
*/
public abstract byte[] doFinal(byte[] bytes)
throws IllegalStateException, IllegalBlockSizeException,
BadPaddingException, TokenException;
/**
* Completes an cipher operation.
* @param bytes Bytes of plaintext (if encrypting) or ciphertext (if
* decrypting).
* @param offset The index in bytes
at which to begin reading.
* @param length The number of bytes from bytes
to read.
* @return The last of the output.
*/
public abstract byte[] doFinal(byte[] bytes, int offset, int length)
throws IllegalStateException, IllegalBlockSizeException,
BadPaddingException, TokenException;
/**
* Completes an cipher operation.
* @return The last of the output.
*/
public abstract byte[] doFinal()
throws IllegalStateException, IllegalBlockSizeException,
BadPaddingException, TokenException;
/**
* Pads a byte array so that its length is a multiple of the given
* blocksize. The method of padding is the one defined in the RSA
* PKCS standards. If M is the length of the data and
* B is the block size, the padding string consists of
* B - (M mod B) octets, each having the value
* B - (M mod B).
* @param toBePadded The byte array to pad.
* @param blockSize The block size of the encryption algorithm. Must be greater
* than zero.
* @see #unPad
*/
public static byte[]
pad(byte[] toBePadded, int blockSize) {
assert(blockSize > 0);
// the padOctet is also the number of pad octets
byte padOctet = (byte) (blockSize - (toBePadded.length % blockSize));
byte[] padded = new byte[toBePadded.length + padOctet];
System.arraycopy(toBePadded, 0, padded, 0, toBePadded.length);
for(int i = toBePadded.length; i < padded.length; i++) {
padded[i] = padOctet;
}
return padded;
}
/**
* Un-pads a byte array that is padded with PKCS padding.
*
* @param blockSize The block size of the encryption algorithm. This
* is only used for error checking: if the pad size is not
* between 1 and blockSize, a BadPaddingException is thrown.
*
* @see #pad
*/
public static byte[]
unPad(byte[] padded, int blockSize) throws BadPaddingException {
if(padded.length == 0) {
return new byte[0];
}
if( padded.length < blockSize ) {
throw new BadPaddingException("Length of padded array is less than"+
" one block");
}
byte padOctet = padded[padded.length-1];
if(padOctet > blockSize) {
throw new BadPaddingException("Padding octet ("+padOctet+") is "+
"larger than block size ("+blockSize+")");
}
if(padOctet < 1) {
throw new BadPaddingException("Padding octet is less than 1");
}
byte[] unpadded = new byte[padded.length - padOctet];
System.arraycopy(padded, 0, unpadded, 0, unpadded.length);
return unpadded;
}
/**
* Un-pads a byte array that is padded with PKCS padding. Since
* this version does not take block size as a parameter, it cannot
* error check.
* @see #pad
*/
public static byte[]
unPad(byte[] padded) throws BadPaddingException {
if(padded.length == 0) {
return new byte[0];
}
byte padOctet = padded[padded.length-1];
if(padOctet < 1) {
throw new BadPaddingException("Padding octet is less than 1");
} else if(padOctet >= padded.length) {
throw new BadPaddingException("Padding is larger than entire"+
" array");
}
byte[] unpadded = new byte[padded.length - padOctet];
System.arraycopy(padded, 0, unpadded, 0, unpadded.length);
return unpadded;
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/CryptoStore.java 0000664 0000000 0000000 00000016473 14565430767 0025437 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.crypto;
import java.security.PublicKey;
import org.mozilla.jss.NotInitializedException;
import org.mozilla.jss.util.Password;
/**
* This is an interface for a permanent repository of cryptographic objects,
* such as keys, certs, and passwords.
*/
public interface CryptoStore {
////////////////////////////////////////////////////////////
// Private Keys
////////////////////////////////////////////////////////////
/**
* Imports a raw private key into this token (permanently).
*
* @param key The private key.
* @exception TokenException If the key cannot be imported to this token.
* @exception KeyAlreadyImportedException If the key already exists on this token.
*/
public PrivateKey
importPrivateKey( byte[] key,
PrivateKey.Type type )
throws TokenException, KeyAlreadyImportedException;
/**
* Imports a raw private key into this token.
*
* @param key The private key.
* @param temporary Whether the key should be temporary.
* @exception TokenException If the key cannot be imported to this token.
* @exception KeyAlreadyImportedException If the key already exists on this token.
*/
public PrivateKey
importPrivateKey( byte[] key,
PrivateKey.Type type, boolean temporary)
throws TokenException, KeyAlreadyImportedException;
/**
* Returns all private keys stored on this token.
*
* @return An array of all private keys stored on this token.
* @exception TokenException If an error occurs on the token while
* gathering the keys.
*/
public PrivateKey[] getPrivateKeys() throws TokenException;
/**
* Returns all public keys stored on this token.
*
* @return An array of all public keys stored on this token.
* @exception TokenException If an error occurs on the token while
* gathering the keys.
*/
public PublicKey[] getPublicKeys() throws TokenException;
/**
* Returns the public key corresponding to the private key.
*
* @param privateKey
* @return The corresponding public key.
* @throws ObjectNotFoundException If the corresponding public key is not found.
* @throws TokenException If an error occurs on the token.
*/
public PublicKey findPublicKey(PrivateKey privateKey)
throws ObjectNotFoundException, TokenException;
/**
* Returns all symmetric keys stored on this token.
*
* @return An array of all symmetric keys stored on this token.
* @exception TokenException If an error occurs on the token while
* gathering the keys.
*/
public SymmetricKey[] getSymmetricKeys() throws TokenException;
/**
* Permanently deletes a private key from the token.
*
* @param privateKey A private key to be permanently deleted.
* @exception NoSuchItemOnTokenException If the given private key does
* not reside on this token.
* @exception TokenException If an error occurs on the token while
* deleting the key.
*/
public void deletePrivateKey(PrivateKey privateKey)
throws NoSuchItemOnTokenException, TokenException;
/**
* Permanently deletes a public key from the token.
*
* @param publicKey A public key to be permanently deleted.
* @exception NoSuchItemOnTokenException If the given public key does
* not reside on this token.
* @exception TokenException If an error occurs on the token while
* deleting the key.
*/
public void deletePublicKey(PublicKey publicKey)
throws NoSuchItemOnTokenException, TokenException;
/**
* Get an encrypted private key for the given cert.
*
* @param cert Certificate of key to be exported
* @param pbeAlg The PBEAlgorithm to use
* @param pw The password to encrypt with
* @param iteration Iteration count; default of 2000 if le 0
*/
public byte[] getEncryptedPrivateKeyInfo(X509Certificate cert,
PBEAlgorithm pbeAlg, Password pw, int iteration)
throws NotInitializedException,
ObjectNotFoundException, TokenException;
/**
* Get an encrypted private key, with optional password
* conversion.
*
* @param conv Password converter. If null, pw.getByteCopy()
* will be used to get password bytes.
* @param pw The password
* @param alg The encryption algorithm
* @param n Iteration count; default of 2000 if le 0
* @param k The private key
*/
public byte[] getEncryptedPrivateKeyInfo(
KeyGenerator.CharToByteConverter conv,
Password pw,
Algorithm alg,
int n,
PrivateKey k);
/**
* @param conv Password converter. If null, pw.getByteCopy()
* will be used to get password bytes.
* @param pw The password
* @param nickname Nickname to use for private key
* @param pubKey Public key corresponding to private key
*/
public void importEncryptedPrivateKeyInfo(
KeyGenerator.CharToByteConverter conv,
Password pw,
String nickname,
PublicKey pubKey,
byte[] epkiBytes);
////////////////////////////////////////////////////////////
// Certs
////////////////////////////////////////////////////////////
/**
* Returns all user certificates stored on this token. A user certificate
* is one that has a matching private key.
*
* @return An array of all user certificates present on this token.
* @exception TokenException If an error occurs on the token while
* gathering the certificates.
*/
public X509Certificate[] getCertificates() throws TokenException;
/**
* Imports a certificate into this token.
*
* @param certBytes Certificate binaries
* @param nickname Certificate nickname
* @return X509Certificate object of the imported certificate
* @throws TokenException
*/
public X509Certificate importCert(byte[] certBytes, String nickname)
throws TokenException;
/**
* Deletes a certificate and the corresponding keys.
*
* @param cert A certificate to be deleted from this token. The cert
* must actually reside on this token.
* @exception NoSuchItemOnTokenException If the given cert does not
* reside on this token.
* @exception TokenException If an error occurred on the token while
* deleting the certificate.
*/
public void deleteCert(X509Certificate cert)
throws NoSuchItemOnTokenException, TokenException;
/**
* Deletes a certificate without deleting the corresponding keys.
*
* @param cert A certificate to be deleted from this token. The cert
* must actually reside on this token.
* @exception NoSuchItemOnTokenException If the given cert does not
* reside on this token.
* @exception TokenException If an error occurred on the token while
* deleting the certificate.
*/
public void deleteCertOnly(X509Certificate cert)
throws NoSuchItemOnTokenException, TokenException;
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/CryptoToken.java 0000664 0000000 0000000 00000027016 14565430767 0025416 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.crypto;
import java.security.DigestException;
import java.security.InvalidKeyException;
import java.security.InvalidParameterException;
import java.security.PublicKey;
import org.mozilla.jss.util.IncorrectPasswordException;
import org.mozilla.jss.util.PasswordCallback;
/**
* A CryptoToken performs cryptographic operations and stores
* cryptographic items, such as keys and certs. It corresponds to a
* Cryptographic Service Provider (CSP) in CDSA, and to a PKCS #11 token.
*
* Instances of CryptoToken are obtained from CryptoManager.
*
* @see org.mozilla.jss.CryptoManager
*/
public interface CryptoToken {
//
// SERVICES
//
/**
* Creates a Signature object, which can perform signing and signature
* verification. Signing and verification cryptographic operations will
* take place on this token. The signing key must be located on this
* token.
*
* @param algorithm The algorithm used for the signing/verification.
* @exception java.security.NoSuchAlgorithmException If the given
* algorithm is not supported by this provider.
*/
public abstract org.mozilla.jss.crypto.Signature getSignatureContext(SignatureAlgorithm algorithm)
throws java.security.NoSuchAlgorithmException, TokenException;
/**
* Creates a Digest object. Digesting cryptographic operations will
* take place on this token.
*
* @param algorithm The algorithm used for digesting.
* @exception java.security.NoSuchAlgorithmException If this provider
* does not support the given algorithm.
*/
public abstract JSSMessageDigest getDigestContext(DigestAlgorithm algorithm)
throws java.security.NoSuchAlgorithmException, DigestException;
// !!! MAC ???
/**
* Creates a Cipher object, which can be used for encryption and
* decryption. Cryptographic operations will take place on this token.
* The keys used in the operations must be located on this token.
*
* @param algorithm The algorithm used for encryption/decryption.
* @exception java.security.NoSuchAlgorithmException If this provider
* does not support the given algorithm.
*/
public abstract Cipher getCipherContext(EncryptionAlgorithm algorithm)
throws java.security.NoSuchAlgorithmException, TokenException;
public abstract SymmetricKeyDeriver getSymmetricKeyDeriver()
throws TokenException;
public abstract KeyWrapper getKeyWrapper(KeyWrapAlgorithm algorithm)
throws java.security.NoSuchAlgorithmException, TokenException;
/**
* Returns a Random Number Generator implemented on this token.
*
* @exception org.mozilla.jss.crypto.ServiceNotProvidedException If this token
* does not perform random number generation
*/
/*
public abstract SecureRandom getRandomGenerator()
throws NotImplementedException, TokenException;
*/
// !!! Derive Keys ???
/**
* Creates a KeyGenerator object, which can be used to generate
* symmetric encryption keys. Any keys generated with this KeyGenerator
* will be generated on this token.
*
* @param algorithm The algorithm that the keys will be used with.
* @exception java.security.NoSuchAlgorithmException If this token does not
* support the given algorithm.
*/
public abstract KeyGenerator getKeyGenerator(KeyGenAlgorithm algorithm)
throws java.security.NoSuchAlgorithmException, TokenException;
/**
* Clones a SymmetricKey from a different token onto this token.
*
* @exception SymmetricKey.NotExtractableException If the key material
* cannot be extracted from the current token.
* @exception InvalidKeyException If the owning token cannot process
* the key to be cloned.
*/
public SymmetricKey cloneKey(SymmetricKey key)
throws SymmetricKey.NotExtractableException,
InvalidKeyException, TokenException;
/**
* Creates a KeyPairGenerator object, which can be used to generate
* key pairs. Any keypairs generated with this generator will be generated
* on this token.
*
* @param algorithm The algorithm that the keys will be used with (RSA,
* DSA, EC, etc.)
* @exception java.security.NoSuchAlgorithmException If this token does
* not support the given algorithm.
*/
public abstract KeyPairGenerator getKeyPairGenerator(KeyPairAlgorithm algorithm)
throws java.security.NoSuchAlgorithmException, TokenException;
/**
* Generates a b64 encoded PKCS10 blob used for making cert
* request. Begin/End brackets included.
*
* @param subject subject dn of the certificate
* @param keysize size of the key
* @param keyType "rsa" or "dsa"
* @param P The DSA prime parameter
* @param Q The DSA sub-prime parameter
* @param G The DSA base parameter
* @return base64 encoded pkcs10 certificate request with
* Begin/end brackets
*/
public abstract String generateCertRequest(String subject, int keysize,
String keyType,
byte[] P, byte[] Q,
byte[] G)
throws TokenException, InvalidParameterException,
PQGParamGenException;
/**
* Determines whether this token supports the given algorithm.
*
* @param alg A JSS algorithm. Note that for Signature, a token may
* fail to support a specific SignatureAlgorithm (such as
* RSASignatureWithMD5Digest) even though it does support the
* generic algorithm (RSASignature). In this case, the signature
* operation will be performed on that token, but the digest
* operation will be performed on the internal token.
* @return true if the token supports the algorithm.
*/
public boolean doesAlgorithm(Algorithm alg);
/**
* Login to the token. If a token is logged in, it will not trigger
* password callbacks.
*
* @param pwcb The password callback for this token.
* @exception IncorrectPasswordException If the supplied password is
* incorrect.
* @see #setLoginMode
* @see org.mozilla.jss.CryptoManager#setPasswordCallback
*/
public abstract void login(PasswordCallback pwcb)
throws IncorrectPasswordException, TokenException;
/**
* Logout of the token.
*
*/
public abstract void logout() throws TokenException;
/**
* Login once, never need to re-enter the password until you log out.
*/
public static final int ONE_TIME = 0;
/**
* Need to re-login after a period of time.
*
* @see org.mozilla.jss.crypto.CryptoToken#setLoginTimeoutMinutes
*/
public static final int TIMEOUT = 1;
/**
* Need to provide a password before each crypto operation.
*/
public static final int EVERY_TIME = 2;
/**
* Returns the login mode of this token: ONE_TIME, TIMEOUT, or
* EVERY_TIME. The default is ONE_TIME.
*
* @see #getLoginTimeoutMinutes
* @exception TokenException If an error occurs on the token.
*/
public abstract int getLoginMode() throws TokenException;
/**
* Sets the login mode of this token.
*
* @param mode ONE_TIME, TIMEOUT, or EVERY_TIME
* @exception TokenException If this mode is not supported by this token,
* or an error occurs on the token.
* @see #login
* @see #setLoginTimeoutMinutes
*/
public abstract void setLoginMode(int mode) throws TokenException;
/**
* Returns the login timeout period. The timeout is only used if the
* login mode is TIMEOUT.
*
* @see #getLoginMode
* @exception TokenException If an error occurs on the token.
*/
public abstract int getLoginTimeoutMinutes() throws TokenException;
/**
* Sets the timeout period for logging in. This will only be used
* if the login mode is TIMEOUT.
*
* @exception TokenException If timeouts are not supported by this
* token, or an error occurs on the token.
* @see #setLoginMode
*/
public abstract void setLoginTimeoutMinutes(int timeoutMinutes)
throws TokenException;
/**
* Find out if the token is currently logged in.
*
* @see #login
* @see #logout
*/
public boolean isLoggedIn() throws TokenException;
/**
* returns true if this token needs to be logged into before
* it can be used.
*
* @see #login
* @see #logout
*/
public boolean needsLogin() throws TokenException;
/**
* Initialize the password of this token.
*
* @param securityOfficerPW A callback to obtain the password of the
* SecurityOfficer. Pass in a NullPasswordCallback if there is
* no security officer password. Must not be null.
* @param userPW A callback to obtain the new password for this token.
* Must not be null.
* @exception IncorrectPasswordException If the supplied security officer
* password is incorrect.
* @exception AlreadyInitializedException If the token only allows one
* password initialization, and it has already occurred.
* @exception TokenException If an error occurs on the token.
*/
public abstract void initPassword(PasswordCallback securityOfficerPW, PasswordCallback userPW)
throws IncorrectPasswordException, AlreadyInitializedException,
TokenException;
/**
* Determine whether the password has been initialized yet. Some tokens
* (such as the Netscape Internal Key Token) don't allow initializing
* the PIN more than once.
*
* @exception TokenException If an error occurs on the token.
*/
public abstract boolean passwordIsInitialized() throws TokenException;
/**
* Change the password of this token.
*
* @exception IncorrectPasswordException If the supplied old password is
* incorrect.
* @param oldpw A callback (which could be just a Password) to retrieve
* the current password.
* @param newpw A callback (which could be just a Password) to retrieve
* the new password.
*/
public abstract void changePassword(PasswordCallback oldpw, PasswordCallback newpw)
throws IncorrectPasswordException, TokenException;
/**
* Obtain the nickname, or label, of this token.
*
* @exception TokenException If an error occurs on the token.
*/
public abstract String getName() throws TokenException;
/**
* Get the CryptoStore interface to this token's objects.
*/
public abstract CryptoStore getCryptoStore();
/**
* Deep comparison operation. Use this, rather than ==, to determine
* whether two CryptoTokens are the same.
*/
@Override
public boolean equals(Object object);
/**
* Determines whether this token is currently present.
* This could return false if the token is a smart card that was
* removed from its slot.
*/
public boolean isPresent();
public void importPublicKey(
PublicKey pubKey,
boolean permanent)
throws TokenException;
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/DigestAlgorithm.java 0000664 0000000 0000000 00000005641 14565430767 0026223 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.crypto;
import java.security.NoSuchAlgorithmException;
import java.util.Hashtable;
import org.mozilla.jss.asn1.OBJECT_IDENTIFIER;
public class DigestAlgorithm extends Algorithm {
// The size in bytes of the output of this hash.
private int outputSize;
protected DigestAlgorithm(int oidIndex, String name,
OBJECT_IDENTIFIER oid, int outputSize)
{
super(oidIndex, name, oid);
this.outputSize = outputSize;
// only store the first algorithm for a given oid. More than one
// alg might share the same oid, such as from child classes.
if( oid != null && oidMap.get(oid)==null ) {
oidMap.put(oid, this);
}
}
///////////////////////////////////////////////////////////////////////
// OID mapping
///////////////////////////////////////////////////////////////////////
private static Hashtable oidMap = new Hashtable<>();
public static DigestAlgorithm fromOID(OBJECT_IDENTIFIER oid)
throws NoSuchAlgorithmException
{
DigestAlgorithm alg = oidMap.get(oid);
if( alg == null ) {
throw new NoSuchAlgorithmException();
} else {
return alg;
}
}
/**
* @return The output size in bytes for this algorithm.
*/
public int getOutputSize() {
return outputSize;
}
/**
* The MD2 digest algorithm, from RSA.
*/
public static final DigestAlgorithm MD2 = new DigestAlgorithm
(SEC_OID_MD2, "MD2", OBJECT_IDENTIFIER.RSA_DIGEST.subBranch(2), 16 );
/**
* The MD5 digest algorithm, from RSA.
*/
public static final DigestAlgorithm MD5 = new DigestAlgorithm
(SEC_OID_MD5, "MD5", OBJECT_IDENTIFIER.RSA_DIGEST.subBranch(5), 16 );
/**
* The SHA-1 digest algorithm, from Uncle Sam.
*/
@Deprecated(since="5.0.1", forRemoval=true)
public static final DigestAlgorithm SHA1 = new DigestAlgorithm
(SEC_OID_SHA1, "SHA-1", OBJECT_IDENTIFIER.ALGORITHM.subBranch(26), 20);
/*
* The SHA-256 digest Algorithm from FIPS 180-2
*/
public static final DigestAlgorithm SHA256 = new DigestAlgorithm
(SEC_OID_SHA256, "SHA-256", OBJECT_IDENTIFIER.HASH_ALGORITHM.subBranch(1), 32);
/*
* The SHA-384 digest Algorithm from FIPS 180-2
*/
public static final DigestAlgorithm SHA384 = new DigestAlgorithm
(SEC_OID_SHA384, "SHA-384", OBJECT_IDENTIFIER.HASH_ALGORITHM.subBranch(2), 48);
/*
* The SHA-512 digest Algorithm from FIPS 180-2
*/
public static final DigestAlgorithm SHA512 = new DigestAlgorithm
(SEC_OID_SHA512, "SHA-512", OBJECT_IDENTIFIER.HASH_ALGORITHM.subBranch(3), 64);
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/EncryptionAlgorithm.java 0000664 0000000 0000000 00000037362 14565430767 0027143 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.crypto;
import java.security.NoSuchAlgorithmException;
import java.util.Hashtable;
import java.util.Vector;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.RC2ParameterSpec;
import org.mozilla.jss.asn1.OBJECT_IDENTIFIER;
/**
* An algorithm for performing symmetric encryption.
*/
public class EncryptionAlgorithm extends Algorithm {
public static class Mode {
private String name;
private static Hashtable nameHash = new Hashtable<>();
private Mode() {
}
private Mode(String name) {
this.name = name;
nameHash.put(name.toLowerCase(), this);
}
public static Mode fromString(String name)
throws NoSuchAlgorithmException {
Mode m = nameHash.get(name.toLowerCase());
if (m == null) {
throw new NoSuchAlgorithmException(
"Unrecognized mode \"" + name + "\"");
}
return m;
}
@Override
public String toString() {
return name;
}
public static final Mode NONE = new Mode("NONE");
public static final Mode ECB = new Mode("ECB");
public static final Mode CBC = new Mode("CBC");
}
public static class Alg {
private String name;
private static Hashtable nameHash = new Hashtable<>();
private Alg() {
}
private Alg(String name) {
this.name = name;
nameHash.put(name.toLowerCase(), this);
}
private static Alg fromString(String name)
throws NoSuchAlgorithmException {
Alg a = nameHash.get(name.toLowerCase());
if (a == null) {
throw new NoSuchAlgorithmException("Unrecognized algorithm \""
+ name + "\"");
}
return a;
}
@Override
public String toString() {
return name;
}
public static final Alg RC4 = new Alg("RC4");
public static final Alg DES = new Alg("DES");
public static final Alg DESede = new Alg("DESede");
public static final Alg AES = new Alg("AES");
public static final Alg RC2 = new Alg("RC2");
}
public static class Padding {
private String name;
private static Hashtable nameHash = new Hashtable<>();
private Padding() {
}
private Padding(String name) {
this.name = name;
nameHash.put(name.toLowerCase(), this);
}
@Override
public String toString() {
return name;
}
public static Padding fromString(String name)
throws NoSuchAlgorithmException {
Padding p = nameHash.get(name.toLowerCase());
if (p == null) {
throw new NoSuchAlgorithmException("Unrecognized Padding " +
"type \"" + name + "\"");
}
return p;
}
public static final Padding NONE = new Padding("NoPadding");
public static final Padding PKCS5 = new Padding("PKCS5Padding");
}
private static String makeName(Alg alg, Mode mode, Padding padding) {
StringBuffer buf = new StringBuffer();
buf.append(alg.toString());
buf.append('/');
buf.append(mode.toString());
buf.append('/');
buf.append(padding.toString());
return buf.toString();
}
protected EncryptionAlgorithm(int oidTag, Alg alg, Mode mode,
Padding padding, Class> paramClass, int blockSize,
OBJECT_IDENTIFIER oid, int keyStrength) {
super(oidTag, makeName(alg, mode, padding), oid, paramClass);
this.alg = alg;
this.mode = mode;
this.padding = padding;
this.blockSize = blockSize;
if (oid != null) {
oidMap.put(oid, this);
}
if (name != null) {
nameMap.put(name.toLowerCase(), this);
}
this.keyStrength = keyStrength;
algList.addElement(this);
}
protected EncryptionAlgorithm(int oidTag, Alg alg, Mode mode,
Padding padding, Class>[] paramClasses, int blockSize,
OBJECT_IDENTIFIER oid, int keyStrength) {
super(oidTag, makeName(alg, mode, padding), oid, paramClasses);
this.alg = alg;
this.mode = mode;
this.padding = padding;
this.blockSize = blockSize;
if (oid != null) {
oidMap.put(oid, this);
}
if (name != null) {
nameMap.put(name.toLowerCase(), this);
}
this.keyStrength = keyStrength;
algList.addElement(this);
}
protected EncryptionAlgorithm(int oidTag, Alg alg, Mode mode,
Padding padding, Class> paramClass, int blockSize,
OBJECT_IDENTIFIER oid, int keyStrength,String name)
{
super(oidTag, name, oid, paramClass);
this.alg = alg;
this.mode = mode;
this.padding = padding;
this.blockSize = blockSize;
if(oid!=null) {
oidMap.put(oid, this);
}
if( name != null ) {
nameMap.put(name.toLowerCase(), this);
}
this.keyStrength = keyStrength;
algList.addElement(this);
}
protected EncryptionAlgorithm(int oidTag, Alg alg, Mode mode,
Padding padding, Class> []paramClasses, int blockSize,
OBJECT_IDENTIFIER oid, int keyStrength,String name)
{
super(oidTag, name, oid, paramClasses);
this.alg = alg;
this.mode = mode;
this.padding = padding;
this.blockSize = blockSize;
if(oid!=null) {
oidMap.put(oid, this);
}
if( name != null ) {
nameMap.put(name.toLowerCase(), this);
}
this.keyStrength = keyStrength;
algList.addElement(this);
}
private int blockSize;
private Alg alg;
private Mode mode;
private Padding padding;
private int keyStrength;
/**
* @return The base algorithm, without the parameters. For example,
* the base algorithm of "AES/CBC/NoPadding" is "AES".
*/
public Alg getAlg() {
return alg;
}
/**
* @return The mode of this algorithm.
*/
public Mode getMode() {
return mode;
}
/**
* @return The padding type of this algorithm.
*/
public Padding getPadding() {
return padding;
}
/**
* @return The key strength of this algorithm in bits. Algorithms that
* use continuously variable key sizes (such as RC4) will return 0 to
* indicate they can use any key size.
*/
public int getKeyStrength() {
return keyStrength;
}
///////////////////////////////////////////////////////////////////////
// mapping
///////////////////////////////////////////////////////////////////////
private static Hashtable oidMap = new Hashtable<>();
private static Hashtable nameMap = new Hashtable<>();
private static Vector algList = new Vector<>();
public static EncryptionAlgorithm fromOID(OBJECT_IDENTIFIER oid)
throws NoSuchAlgorithmException {
Object alg = oidMap.get(oid);
if (alg == null) {
throw new NoSuchAlgorithmException("OID: " + oid.toString());
} else {
return (EncryptionAlgorithm) alg;
}
}
// Note: after we remove this deprecated method, we can remove
// nameMap.
/**
* @param name Algorithm name.
* @return Encryption algorithm.
* @throws NoSuchAlgorithmException If the algorithm is not found.
* @deprecated This method is deprecated because algorithm strings
* don't contain key length, which is necessary to distinguish between
* AES algorithms.
*/
@Deprecated
public static EncryptionAlgorithm fromString(String name)
throws NoSuchAlgorithmException {
Object alg = nameMap.get(name.toLowerCase());
if (alg == null) {
throw new NoSuchAlgorithmException();
} else {
return (EncryptionAlgorithm) alg;
}
}
public static EncryptionAlgorithm lookup(String algName, String modeName,
String paddingName, int keyStrength)
throws NoSuchAlgorithmException {
int len = algList.size();
Alg alg = Alg.fromString(algName);
Mode mode = Mode.fromString(modeName);
Padding padding;
if (paddingName == null || paddingName.equals("")) {
padding = Padding.NONE;
} else {
padding = Padding.fromString(paddingName);
}
int i;
for (i = 0; i < len; ++i) {
EncryptionAlgorithm cur = algList.elementAt(i);
if (cur.alg == alg && cur.mode == mode && cur.padding == padding) {
if (cur.keyStrength == 0 || cur.keyStrength == keyStrength) {
break;
}
}
}
if (i == len) {
throw new NoSuchAlgorithmException(algName + "/" + modeName + "/"
+ paddingName + " with key strength " + keyStrength +
" not found");
}
return algList.elementAt(i);
}
/**
* @return The blocksize of the algorithm in bytes. Stream algorithms (such as
* RC4) have a blocksize of 1.
*/
public int getBlockSize() {
return blockSize;
}
/**
* @return true
if this algorithm performs padding.
*/
public boolean isPadded() {
return !Padding.NONE.equals(padding);
}
/**
* @return The type of padding for this algorithm.
*/
public Padding getPaddingType() {
return padding;
}
private static Class>[] IVParameterSpecClasses = null;
static {
IVParameterSpecClasses = new Class[2];
IVParameterSpecClasses[0] = IVParameterSpec.class;
IVParameterSpecClasses[1] = IvParameterSpec.class;
}
/**
* Returns the number of bytes that this algorithm expects in
* its initialization vector.
*
* @return The size in bytes of the IV for this algorithm. A size of
* 0 means this algorithm does not take an IV.
*/
public native int getIVLength();
public static final EncryptionAlgorithm RC4 = new EncryptionAlgorithm(SEC_OID_RC4, Alg.RC4, Mode.NONE, Padding.NONE,
(Class>) null, 1, OBJECT_IDENTIFIER.RSA_CIPHER.subBranch(4), 0);
public static final EncryptionAlgorithm DES_ECB = new EncryptionAlgorithm(SEC_OID_DES_ECB, Alg.DES, Mode.ECB,
Padding.NONE, (Class>) null, 8, OBJECT_IDENTIFIER.ALGORITHM.subBranch(6),
56);
public static final EncryptionAlgorithm DES_CBC = new EncryptionAlgorithm(SEC_OID_DES_CBC, Alg.DES, Mode.CBC,
Padding.NONE, IVParameterSpecClasses, 8,
OBJECT_IDENTIFIER.ALGORITHM.subBranch(7), 56);
public static final EncryptionAlgorithm DES_CBC_PAD = new EncryptionAlgorithm(CKM_DES_CBC_PAD, Alg.DES, Mode.CBC,
Padding.PKCS5, IVParameterSpecClasses, 8, null, 56); // no oid
public static final EncryptionAlgorithm DES3_ECB = new EncryptionAlgorithm(CKM_DES3_ECB, Alg.DESede, Mode.ECB,
Padding.NONE, (Class>) null, 8, null, 168); // no oid
public static final EncryptionAlgorithm DES3_CBC = new EncryptionAlgorithm(SEC_OID_DES_EDE3_CBC, Alg.DESede,
Mode.CBC, Padding.NONE, IVParameterSpecClasses, 8,
OBJECT_IDENTIFIER.RSA_CIPHER.subBranch(7), 168);
public static final EncryptionAlgorithm DES3_CBC_PAD = new EncryptionAlgorithm(CKM_DES3_CBC_PAD, Alg.DESede,
Mode.CBC, Padding.PKCS5, IVParameterSpecClasses, 8,
null, 168); //no oid
public static final EncryptionAlgorithm RC2_CBC = new EncryptionAlgorithm(SEC_OID_RC2_CBC, Alg.RC2, Mode.CBC,
Padding.NONE, RC2ParameterSpec.class, 8,
null, 0); // no oid, see comment below
// Which algorithm should be associated with this OID, RC2_CBC or
// RC2_CBC_PAD? NSS says RC2_CBC, but PKCS #5 v2.0 says RC2_CBC_PAD.
// See NSS bug 202925.
public static final EncryptionAlgorithm RC2_CBC_PAD = new EncryptionAlgorithm(CKM_RC2_CBC_PAD, Alg.RC2, Mode.CBC,
Padding.PKCS5, RC2ParameterSpec.class, 8,
OBJECT_IDENTIFIER.RSA_CIPHER.subBranch(2), 0);
public static final OBJECT_IDENTIFIER AES_ROOT_OID = new OBJECT_IDENTIFIER(
new long[] { 2, 16, 840, 1, 101, 3, 4, 1 });
public static final EncryptionAlgorithm AES_128_ECB = new EncryptionAlgorithm(SEC_OID_AES_128_ECB,
Alg.AES, Mode.ECB,
Padding.NONE, (Class>) null, 16,
AES_ROOT_OID.subBranch(1), 128);
public static final EncryptionAlgorithm AES_128_CBC = new EncryptionAlgorithm(SEC_OID_AES_128_CBC,
Alg.AES, Mode.CBC,
Padding.NONE, IVParameterSpecClasses, 16,
AES_ROOT_OID.subBranch(2), 128);
public static final EncryptionAlgorithm AES_128_CBC_PAD = new EncryptionAlgorithm(SEC_OID_AES_128_CBC,
Alg.AES, Mode.CBC,
Padding.PKCS5, IVParameterSpecClasses, 16,
AES_ROOT_OID.subBranch(2), 128);
public static final EncryptionAlgorithm AES_192_ECB = new EncryptionAlgorithm(SEC_OID_AES_192_ECB,
Alg.AES, Mode.ECB,
Padding.NONE, (Class>) null, 16, AES_ROOT_OID.subBranch(21), 192);
public static final EncryptionAlgorithm AES_192_CBC = new EncryptionAlgorithm(SEC_OID_AES_192_CBC,
Alg.AES, Mode.CBC,
Padding.NONE, IVParameterSpecClasses, 16,
AES_ROOT_OID.subBranch(22), 192);
public static final EncryptionAlgorithm AES_192_CBC_PAD = new EncryptionAlgorithm(SEC_OID_AES_192_CBC,
Alg.AES, Mode.CBC,
Padding.PKCS5, IVParameterSpecClasses, 16,
AES_ROOT_OID.subBranch(22), 192);
public static final EncryptionAlgorithm AES_256_ECB = new EncryptionAlgorithm(SEC_OID_AES_256_ECB,
Alg.AES, Mode.ECB,
Padding.NONE, (Class>) null, 16, AES_ROOT_OID.subBranch(41), 256);
public static final EncryptionAlgorithm AES_256_CBC = new EncryptionAlgorithm(SEC_OID_AES_256_CBC,
Alg.AES, Mode.CBC,
Padding.NONE, IVParameterSpecClasses, 16,
AES_ROOT_OID.subBranch(42), 256);
public static final EncryptionAlgorithm AES_CBC_PAD = new EncryptionAlgorithm(CKM_AES_CBC_PAD, Alg.AES, Mode.CBC,
Padding.PKCS5, IVParameterSpecClasses, 16, null, 256); // no oid
public static final EncryptionAlgorithm AES_256_CBC_PAD = new EncryptionAlgorithm(SEC_OID_AES_256_CBC,
Alg.AES, Mode.CBC,
Padding.PKCS5, IVParameterSpecClasses, 16,
AES_ROOT_OID.subBranch(42), 256);
public static final EncryptionAlgorithm
AES_128_KEY_WRAP_KWP = new EncryptionAlgorithm(SEC_OID_AES_128_KEY_WRAP_KWP,
Alg.AES,Mode.NONE,
Padding.PKCS5, IVParameterSpecClasses, 16,
AES_ROOT_OID.subBranch(8), 128,"AES/None/PKCS5Padding/Kwp/128");
public static final EncryptionAlgorithm
AES_192_KEY_WRAP_KWP = new EncryptionAlgorithm(SEC_OID_AES_192_KEY_WRAP_KWP,
Alg.AES,Mode.NONE,
Padding.PKCS5, IVParameterSpecClasses, 16,
AES_ROOT_OID.subBranch(28), 192,"AES/None/PKCSPadding/Kwp/192");
public static final EncryptionAlgorithm
AES_256_KEY_WRAP_KWP = new EncryptionAlgorithm(SEC_OID_AES_256_KEY_WRAP_KWP,
Alg.AES,Mode.NONE,
Padding.PKCS5, IVParameterSpecClasses, 16,
AES_ROOT_OID.subBranch(48), 256,"AES/None/PKCS5Padding/Kwp/256");
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/HMACAlgorithm.java 0000664 0000000 0000000 00000004663 14565430767 0025517 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.crypto;
import java.security.NoSuchAlgorithmException;
import java.util.Hashtable;
import org.mozilla.jss.asn1.OBJECT_IDENTIFIER;
/**
* Algorithms for performing HMACs. These can be used to create
* MessageDigests.
*/
public class HMACAlgorithm extends DigestAlgorithm {
protected HMACAlgorithm(int oidIndex, String name, OBJECT_IDENTIFIER oid,
int outputSize) {
super(oidIndex, name, oid, outputSize);
if( oid!=null && oidMap.get(oid)==null) {
oidMap.put(oid, this);
}
}
///////////////////////////////////////////////////////////////////////
// OID mapping
///////////////////////////////////////////////////////////////////////
private static Hashtable oidMap = new Hashtable<>();
/**
* Looks up the HMAC algorithm with the given OID.
*
* @param oid OID.
* @return HMAC algorithm.
* @exception NoSuchAlgorithmException If no registered HMAC algorithm
* has the given OID.
*/
public static HMACAlgorithm fromOID(OBJECT_IDENTIFIER oid)
throws NoSuchAlgorithmException
{
Object alg = oidMap.get(oid);
if( alg == null ) {
throw new NoSuchAlgorithmException();
} else {
return (HMACAlgorithm) alg;
}
}
/**
* SHA-X HMAC. This is a Message Authentication Code that uses a
* symmetric key together with SHA-X digesting to create a form of
* signature.
*/
@Deprecated(since="5.0.1", forRemoval=true)
public static final HMACAlgorithm SHA1 = new HMACAlgorithm
(SEC_OID_HMAC_SHA1, "SHA-1-HMAC",
OBJECT_IDENTIFIER.RSA_DIGEST.subBranch(7), 20);
public static final HMACAlgorithm SHA256 = new HMACAlgorithm
(SEC_OID_HMAC_SHA256, "SHA-256-HMAC",
OBJECT_IDENTIFIER.RSA_DIGEST.subBranch(9), 32);
public static final HMACAlgorithm SHA384 = new HMACAlgorithm
(SEC_OID_HMAC_SHA384, "SHA-384-HMAC",
OBJECT_IDENTIFIER.RSA_DIGEST.subBranch(10), 48);
public static final HMACAlgorithm SHA512 = new HMACAlgorithm
(SEC_OID_HMAC_SHA512, "SHA-512-HMAC",
OBJECT_IDENTIFIER.RSA_DIGEST.subBranch(11), 64);
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/IVParameterSpec.java 0000664 0000000 0000000 00000001112 14565430767 0026114 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.crypto;
import javax.crypto.spec.IvParameterSpec;
/**
* An algorithm parameter that consists of an initialization vector (IV).
*/
public class IVParameterSpec extends IvParameterSpec {
public IVParameterSpec(byte[] iv) {
super(iv);
}
public IVParameterSpec(byte[] iv, int offset, int len) {
super(iv, offset, len);
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/IllegalBlockSizeException.java 0000664 0000000 0000000 00000000540 14565430767 0030164 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.crypto;
public class IllegalBlockSizeException extends Exception {
private static final long serialVersionUID = 1L;
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/InternalCertificate.java 0000664 0000000 0000000 00000005654 14565430767 0027060 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.crypto;
import org.mozilla.jss.pkcs11.PK11Cert;
/**
* Certificates residing in the internal database. Their trust flags
* can be viewed and modified. Other types of certificates do not
* have trust flags.
*/
public interface InternalCertificate extends X509Certificate
{
/**
* @deprecated Use PK11Cert.VALID_PEER instead.
*/
@Deprecated
public static final int VALID_PEER = PK11Cert.VALID_PEER;
/**
* @deprecated Use PK11Cert.TRUSTED_PEER instead.
*/
@Deprecated
public static final int TRUSTED_PEER = PK11Cert.TRUSTED_PEER;
/**
* @deprecated Use PK11Cert.VALID_CA instead.
*/
@Deprecated
public static final int VALID_CA = PK11Cert.VALID_CA;
/**
* @deprecated Use PK11Cert.TRUSTED_CA instead.
*/
@Deprecated
public static final int TRUSTED_CA = PK11Cert.TRUSTED_CA;
/**
* @deprecated Use PK11Cert.USER instead.
*/
@Deprecated
public static final int USER = PK11Cert.USER;
/**
* @deprecated Use PK11Cert.TRUSTED_CLIENT_CA instead.
*/
@Deprecated
public static final int TRUSTED_CLIENT_CA = PK11Cert.TRUSTED_CLIENT_CA;
/**
* Set the SSL trust flags for this certificate.
*
* @param trust A bitwise OR of the trust flags VALID_PEER, VALID_CA,
* TRUSTED_CA, USER, and TRUSTED_CLIENT_CA.
*/
public abstract void setSSLTrust(int trust);
/**
* Set the email (S/MIME) trust flags for this certificate.
*
* @param trust A bitwise OR of the trust flags VALID_PEER, VALID_CA,
* TRUSTED_CA, USER, and TRUSTED_CLIENT_CA.
*/
public abstract void setEmailTrust(int trust);
/**
* Set the object signing trust flags for this certificate.
*
* @param trust A bitwise OR of the trust flags VALID_PEER, VALID_CA,
* TRUSTED_CA, USER, and TRUSTED_CLIENT_CA.
*/
public abstract void setObjectSigningTrust(int trust);
/**
* Get the SSL trust flags for this certificate.
*
* @return A bitwise OR of the trust flags VALID_PEER, VALID_CA,
* TRUSTED_CA, USER, and TRUSTED_CLIENT_CA.
*/
public abstract int getSSLTrust();
/**
* Get the email (S/MIME) trust flags for this certificate.
*
* @return A bitwise OR of the trust flags VALID_PEER, VALID_CA,
* TRUSTED_CA, USER, and TRUSTED_CLIENT_CA.
*/
public abstract int getEmailTrust();
/**
* Get the object signing trust flags for this certificate.
*
* @return A bitwise OR of the trust flags VALID_PEER, VALID_CA,
* TRUSTED_CA, USER, and TRUSTED_CLIENT_CA.
*/
public abstract int getObjectSigningTrust();
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/InvalidDERException.java 0000664 0000000 0000000 00000001443 14565430767 0026731 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.crypto;
/**
* This exception is thrown when we encounter a bogus DER blob.
*/
public class InvalidDERException extends Exception {
private static final long serialVersionUID = 1L;
public InvalidDERException() { super(); }
public InvalidDERException(String mesg) { super(mesg); }
public InvalidDERException(String mesg, Throwable cause) { super(mesg, cause); }
public InvalidDERException(String mesg, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(mesg, cause, enableSuppression, writableStackTrace);
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/InvalidKeyFormatException.java 0000664 0000000 0000000 00000001466 14565430767 0030225 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.crypto;
/**
* An exception of this type is thrown if an encoded private key
* cannot be decoded.
*/
public class InvalidKeyFormatException
extends java.security.spec.InvalidKeySpecException
{
private static final long serialVersionUID = 1L;
public InvalidKeyFormatException() {
super();
}
public InvalidKeyFormatException(String mesg) {
super(mesg);
}
public InvalidKeyFormatException(String mesg, Throwable cause) {
super(mesg, cause);
}
public InvalidKeyFormatException(Throwable cause) {
super(cause);
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/JSSMessageDigest.java 0000664 0000000 0000000 00000007510 14565430767 0026236 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.crypto;
import java.security.DigestException;
import java.security.InvalidKeyException;
/**
* A class for performing message digesting (hashing) and MAC operations.
*/
public abstract class JSSMessageDigest {
/**
* Initializes an HMAC digest with the given symmetric key. This also
* has the effect of resetting the digest.
*
* @param key Symmetric key.
* @exception DigestException If this algorithm is not an HMAC algorithm.
* @exception InvalidKeyException If the given key is not valid.
*/
public abstract void initHMAC(SymmetricKey key)
throws DigestException, InvalidKeyException;
/**
* Updates the digest with a single byte of input.
* @param input Input byte.
* @throws DigestException If an error occurred.
*/
public void update(byte input) throws DigestException {
byte[] in = { input };
update(in, 0, 1);
}
/**
* Updates the digest with a portion of an array.
*
* @param input An array from which to update the digest.
* @param offset The index in the array at which to start digesting.
* @param len The number of bytes to digest.
* @exception DigestException If an error occurs while digesting.
*/
public abstract void update(byte[] input, int offset, int len)
throws DigestException;
/**
* Updates the digest with an array.
*
* @param input An array to feed to the digest.
* @exception DigestException If an error occurs while digesting.
*/
public void update(byte[] input) throws DigestException {
update(input, 0, input.length);
}
/**
* Completes digestion.
*
* @return The, ahem, output of the digest operation.
* @exception DigestException If an error occurs while digesting.
*/
public byte[] digest() throws DigestException {
byte[] output = new byte[getOutputSize()];
digest(output, 0, output.length);
return output;
}
/**
* Completes digesting, storing the result into the provided array.
*
* @param buf The buffer in which to place the digest output.
* @param offset The offset in the buffer at which to store the output.
* @param len The amount of space available in the buffer for the
* digest output.
* @return The number of bytes actually stored into buf.
* @exception DigestException If the provided space is too small for
* the digest, or an error occurs with the digest.
*/
public abstract int digest(byte[] buf, int offset, int len)
throws DigestException;
/**
* Provides final data to the digest, then completes it and returns the
* output.
*
* @param input The digest's last meal.
* @return The completed digest.
* @exception DigestException If an error occurs while digesting.
*/
public byte[] digest(byte[] input) throws DigestException {
update(input);
return digest();
}
/**
* Resets this digest for further use. This clears all input and
* output streams. If this is an HMAC digest, the HMAC key is not
* cleared.
* @throws DigestException If an error occurred.
*/
public abstract void reset() throws DigestException;
/**
* @return The algorithm that this digest uses.
*/
public abstract DigestAlgorithm getAlgorithm();
/**
* Returns the length of the digest created by this digest's
* digest algorithm.
*
* @return The size in bytes of the output of this digest.
*/
public int getOutputSize() {
return getAlgorithm().getOutputSize();
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/JSSOAEPParameterSpec.java 0000664 0000000 0000000 00000014771 14565430767 0026721 0 ustar 00root root 0000000 0000000 package org.mozilla.jss.crypto;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.MGF1ParameterSpec;
import javax.crypto.spec.OAEPParameterSpec;
import javax.crypto.spec.PSource;
import org.mozilla.jss.pkcs11.PKCS11Constants;
import org.mozilla.jss.util.NativeEnclosure;
/**
* This class is utilized by JSS to implement OAEP support.
*
* Unlike the existing OAEPParameterSpec in the JCA, this class supports
* NativeEnclosure, allowing it to be used within low-level JNI calls. We
* support copying from an existing OAEPParameterSpec instance (so use is
* interchangeable within JSS) and support setting members from JSS-specific
* types.
*
* Note that this class cannot be used with other JCA providers natively.
*/
public class JSSOAEPParameterSpec extends NativeEnclosure implements AlgorithmParameterSpec {
public long hashAlg;
public long mgf;
public byte[] sourceData;
public JSSOAEPParameterSpec(String mdName, String mgfName, AlgorithmParameterSpec mgfSpec, PSource pSrc) {
setDigestAlgorithm(mdName);
setMaskGenAlgorithm(mgfName);
setMaskGenAlgorithmType(mgfSpec);
setPSource(pSrc);
}
public JSSOAEPParameterSpec(OAEPParameterSpec copy) {
setDigestAlgorithm(copy.getDigestAlgorithm());
setMaskGenAlgorithm(copy.getMGFAlgorithm());
setMaskGenAlgorithmType(copy.getMGFParameters());
setPSource(copy.getPSource());
}
public void setDigestAlgorithm(String algo) throws IllegalArgumentException {
switch (algo.toLowerCase()) {
case "md5":
case "ckm_md5":
hashAlg = PKCS11Constants.CKM_MD5;
break;
case "sha1":
case "sha-1":
case "ckm_sha_1":
hashAlg = PKCS11Constants.CKM_SHA_1;
break;
case "sha256":
case "sha-256":
case "ckm_sha256":
hashAlg = PKCS11Constants.CKM_SHA256;
break;
case "sha384":
case "sha-384":
case "ckm_sha384":
hashAlg = PKCS11Constants.CKM_SHA384;
break;
case "sha512":
case "sha-512":
case "ckm_sha512":
hashAlg = PKCS11Constants.CKM_SHA512;
break;
default:
String msg = "Unknown algorithm identifier: " + algo;
throw new IllegalArgumentException(msg);
}
}
public void setDigestAlgorithm(DigestAlgorithm algo) throws IllegalArgumentException {
if ((algo instanceof HMACAlgorithm) || (algo instanceof CMACAlgorithm)) {
String msg = "Unable to use MAC digest algorithm " + algo;
msg += " in place of an unkeyed hash algorithm";
throw new IllegalArgumentException(msg);
}
hashAlg = algo.getEnum().getValue();
}
public void setDigestAlgorithm(long algo) throws IllegalArgumentException {
hashAlg = algo;
}
public void setMaskGenAlgorithm(String algo) throws IllegalArgumentException {
if (!algo.toLowerCase().equals("mgf1")) {
String msg = "Unknown mask generation algorithm: " + algo;
throw new IllegalArgumentException(msg);
}
// Do nothing. We just validate this data so if we get passed
// something unexpected, we error out instead.
}
public void setMaskGenAlgorithmType(String algo) throws IllegalArgumentException {
switch (algo.toLowerCase()) {
case "sha1":
case "sha-1":
case "ckm_sha_1":
hashAlg = PKCS11Constants.CKG_MGF1_SHA1;
break;
case "sha256":
case "sha-256":
case "ckm_sha256":
hashAlg = PKCS11Constants.CKG_MGF1_SHA256;
break;
case "sha384":
case "sha-384":
case "ckm_sha384":
hashAlg = PKCS11Constants.CKG_MGF1_SHA384;
break;
case "sha512":
case "sha-512":
case "ckm_sha512":
hashAlg = PKCS11Constants.CKG_MGF1_SHA512;
break;
default:
String msg = "Unknown mask generation algorithm identifier: " + algo;
throw new IllegalArgumentException(msg);
}
}
public void setMaskGenAlgorithmType(AlgorithmParameterSpec algo) throws IllegalArgumentException {
if ( !(algo instanceof MGF1ParameterSpec)) {
String msg = "Unknown mask generation algorithm parameter ";
msg += "specification: " + algo;
throw new IllegalArgumentException(msg);
}
MGF1ParameterSpec mgf1 = (MGF1ParameterSpec) algo;
switch (mgf1.getDigestAlgorithm().toLowerCase()) {
case "sha1":
case "sha-1":
mgf = PKCS11Constants.CKG_MGF1_SHA1;
break;
case "sha256":
case "sha-256":
mgf = PKCS11Constants.CKG_MGF1_SHA256;
break;
case "sha384":
case "sha-384":
mgf = PKCS11Constants.CKG_MGF1_SHA384;
break;
case "sha512":
case "sha-512":
mgf = PKCS11Constants.CKG_MGF1_SHA512;
break;
default:
String msg = "Unknown mask generation algorithm identifier: ";
msg += mgf1.getDigestAlgorithm();
throw new IllegalArgumentException(msg);
}
}
public void setMaskGenAlgorithmType(long algo) throws IllegalArgumentException {
mgf = algo;
}
public void setPSource(PSource spec) throws IllegalArgumentException {
if (spec == null) {
sourceData = null;
return;
}
if (!(spec instanceof PSource.PSpecified)) {
String msg = "Expected PSource spec to be an instance of ";
msg += "PSource.PSpecified, but wasn't: " + spec;
throw new IllegalArgumentException(msg);
}
PSource.PSpecified value = (PSource.PSpecified) spec;
setPSource(value.getValue());
}
public void setPSource(byte[] data) throws IllegalArgumentException {
// PSource.PSpecified.DEFAULT is an allocated byte array of 0 length.
// This confuses JSS_FromByteArray(...) into thinking that an error
// occurred. Because PKCS#11 accepts a NULL pointer to go with a 0
// length array, just set sourceData to NULL.
if (data == null || data.length == 0) {
sourceData = null;
return;
}
sourceData = data;
}
@Override
protected native void acquireNativeResources() throws Exception;
@Override
protected native void releaseNativeResources() throws Exception;
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/JSSSecureRandom.java 0000664 0000000 0000000 00000001412 14565430767 0026074 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.crypto;
/**
* An interface for secure random numbers.
*/
public interface JSSSecureRandom {
/**
* Seed the RNG with the given seed bytes.
* @param seed Seed.
*/
public void setSeed(byte[] seed);
/**
* Seed the RNG with the eight bytes contained in seed
.
* @param seed Seed.
*/
public void setSeed(long seed);
/**
* Retrieves random bytes and stores them in the given array.
* @param bytes Array to store random bytes.
*/
public void nextBytes(byte bytes[]);
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/KBKDFByteArrayParam.java 0000664 0000000 0000000 00000004041 14565430767 0026553 0 ustar 00root root 0000000 0000000 package org.mozilla.jss.crypto;
import java.util.Arrays;
import org.mozilla.jss.pkcs11.PKCS11Constants;
/**
* A KBKDF Byte Array Parameter is a type of KBKDF Data Parameter that
* contains a single byte array that gets passed to the KBKDF to be inserted
* into the PRF input stream.
*/
public class KBKDFByteArrayParam extends KBKDFDataParameter {
private byte[] data;
public KBKDFByteArrayParam() {
super(PKCS11Constants.CK_SP800_108_BYTE_ARRAY);
}
public KBKDFByteArrayParam(byte[] data) throws IllegalArgumentException {
this();
setByteArray(data);
}
public void setByteArray(byte[] data) throws IllegalArgumentException {
if (data == null) {
throw new IllegalArgumentException("Expected non-null byte array!");
}
this.data = Arrays.copyOf(data, data.length);
}
/**
* Zero out the copied contents of the byte array.
*
* Call this method when the contents of this byte array parameter are
* sensitive and they're done being used. Note that this isn't called
* during close() as a given byte array parameter may be used multiple
* times in different KBKDF calls.
*/
public void zeroByteArray() {
if (data == null) {
return;
}
for (int i = 0; i < data.length; i++) {
data[i] = 0;
}
}
@Override
protected void acquireNativeResources() throws Exception {
if (data == null || data.length == 0) {
String msg = "Expected non-null byte array in ";
msg += "KBKDFByteArrayParam but was null! Call setByteArray ";
msg += "to provide a byte array.";
throw new RuntimeException(msg);
}
acquireNativeResourcesInternal();
}
@Override
protected void releaseNativeResources() throws Exception {
releaseNativeResourcesInternal();
}
private native void acquireNativeResourcesInternal() throws Exception;
private native void releaseNativeResourcesInternal() throws Exception;
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/KBKDFCounterParams.java 0000664 0000000 0000000 00000006150 14565430767 0026456 0 ustar 00root root 0000000 0000000 package org.mozilla.jss.crypto;
import org.mozilla.jss.pkcs11.PKCS11Constants;
public class KBKDFCounterParams extends KBKDFParameterSpec {
public KBKDFCounterParams() {
}
@Override
protected void validateParameters() throws IllegalArgumentException {
if (prfKey == null) {
String msg = "Required parameter KDF key was never set.";
throw new IllegalArgumentException(msg);
}
if (prf != PKCS11Constants.CKM_SHA_1_HMAC &&
prf != PKCS11Constants.CKM_SHA256_HMAC &&
prf != PKCS11Constants.CKM_SHA384_HMAC &&
prf != PKCS11Constants.CKM_SHA512_HMAC &&
prf != PKCS11Constants.CKM_AES_CMAC) {
String msg = "Expected Pseudo-Random Function to be SHA1-HMAC, ";
msg += "SHA2-HMAC, or AES-CMAC, but got unknown PKCS#11 ";
msg += "constant: " + prf;
throw new IllegalArgumentException(msg);
}
if (params == null || params.length == 0) {
String msg = "Expected non-null, non-zero length array of KDF ";
msg += "parameters.";
throw new IllegalArgumentException(msg);
}
int index = 0;
for (KBKDFDataParameter param : params) {
if (param instanceof KBKDFOptionalCounterParam) {
String msg = "Got unexpected data parameter at index " + index;
msg += ": KBKDF Optional Counter Parameter is forbidden from ";
msg += "use with Counter mode KBKDF.";
throw new IllegalArgumentException(msg);
}
if (param instanceof KBKDFIterationVariableParam) {
KBKDFIterationVariableParam kivp = (KBKDFIterationVariableParam) param;
if (kivp.widthInBits == -1) {
String msg = "Got unexpected data in KBKDF Iteration ";
msg += "Variable Parameter at index " + index + ": ";
msg += "Expected valid counter specification, but got ";
msg += "widthInBits of -1. Call setCounterSpec(...) ";
msg += "before using this parameter.";
throw new IllegalArgumentException(msg);
}
}
if (param instanceof KBKDFDKMLengthParam) {
KBKDFDKMLengthParam kdlp = (KBKDFDKMLengthParam) param;
if (kdlp.widthInBits == 0) {
String msg = "Got unexpected data in KBKDF DKM Length ";
msg += "Parameter at index " + index + ": Expected valid ";
msg += "length specification, but got widthInBits of 0. ";
msg += "Call setLngthSpec(...) before using this ";
msg += "parameter.";
throw new IllegalArgumentException(msg);
}
}
// Nothing to validate for byte array parameters.
index += 1;
}
}
@Override
protected native void acquireNativeResourcesInternal() throws Exception;
@Override
protected native void releaseNativeResourcesInternal() throws Exception;
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/KBKDFDKMLengthParam.java 0000664 0000000 0000000 00000003057 14565430767 0026434 0 ustar 00root root 0000000 0000000 package org.mozilla.jss.crypto;
import org.mozilla.jss.pkcs11.PKCS11Constants;
/**
* A KBKDF Optional Counter Parameter is a type of KBKDF Data Parameter that
* describes the optional counter variable for Feedback and Pipeline KBKDFs.
*
* Note that this parameter is illegal in Counter Mode.
*/
public class KBKDFDKMLengthParam extends KBKDFDataParameter {
protected long lengthMethod = 1;
protected boolean littleEndian = false;
protected long widthInBits = 0;
public KBKDFDKMLengthParam() {
super(PKCS11Constants.CK_SP800_108_DKM_LENGTH);
}
public KBKDFDKMLengthParam(long lengthMethod, boolean littleEndian, long widthInBits)
throws IllegalArgumentException {
this();
setLengthSpec(lengthMethod, littleEndian, widthInBits);
}
public void setLengthSpec(long lengthMethod, boolean littleEndian, long widthInBits)
throws IllegalArgumentException {
if (widthInBits < 8 || widthInBits > 64) {
throw new IllegalArgumentException("Expected to have width between 8 and 64, but was " + widthInBits);
}
if ((widthInBits % 8) != 0) {
throw new IllegalArgumentException("Expected width to be an even number of bytes, but was " + widthInBits);
}
this.lengthMethod = lengthMethod;
this.littleEndian = littleEndian;
this.widthInBits = widthInBits;
}
@Override
protected native void acquireNativeResources() throws Exception;
@Override
protected native void releaseNativeResources() throws Exception;
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/KBKDFDataParameter.java 0000664 0000000 0000000 00000000634 14565430767 0026406 0 ustar 00root root 0000000 0000000 package org.mozilla.jss.crypto;
import org.mozilla.jss.util.NativeEnclosure;
/**
* A KBKDF Data Parameter is a structure of type CK_PRF_DATA_PARAM, with
* three members: a type, a pointer to its data, and the size of the data
* field.
*/
public abstract class KBKDFDataParameter extends NativeEnclosure {
public long type;
public KBKDFDataParameter(long type) {
this.type = type;
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/KBKDFDerivedKey.java 0000664 0000000 0000000 00000007020 14565430767 0025723 0 ustar 00root root 0000000 0000000 package org.mozilla.jss.crypto;
import java.security.InvalidKeyException;
import java.util.ArrayList;
import java.util.Arrays;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import org.mozilla.jss.pkcs11.attrs.CKAttribute;
import org.mozilla.jss.util.NativeEnclosure;
/**
* Class for supporting additional derived keys from PKCS#11 v3.0's
* SP800-108 KBKDF implementation.
*/
public class KBKDFDerivedKey extends NativeEnclosure {
private CKAttribute[] attrs;
private long handle;
public KBKDFDerivedKey() {
}
public KBKDFDerivedKey(CKAttribute[] attrs) throws IllegalArgumentException {
setAttributes(attrs);
}
public void setAttributes(CKAttribute[] attrs) throws IllegalArgumentException {
if (attrs == null) {
String msg = "Expected populated array of CKAttributes, but ";
msg += "was null.";
throw new IllegalArgumentException(msg);
}
this.attrs = attrs;
}
public void addAttribute(CKAttribute attr) throws IllegalArgumentException {
if (attr == null) {
String msg = "Expected non-null CKAttribute, but was null.";
throw new IllegalArgumentException(msg);
}
ArrayList ck_attrs;
if (attrs == null) {
ck_attrs = new ArrayList<>(1);
} else {
ck_attrs = new ArrayList<>(Arrays.asList(attrs));
}
ck_attrs.add(attr);
this.attrs = ck_attrs.toArray(new CKAttribute[ck_attrs.size()]);
}
@Override
protected void acquireNativeResources() throws Exception {
if (attrs == null) {
String msg = "Expected non-null attributes when trying to ";
msg += "acquire native resources. Call setAttributes(...) ";
msg += "or addAttribute(...) before calling open().";
throw new IllegalArgumentException(msg);
}
for (CKAttribute attr : attrs) {
attr.open();
}
acquireNativeResourcesInternal();
}
@Override
protected void releaseNativeResources() throws Exception {
if (attrs != null) {
for (CKAttribute attr : attrs) {
attr.close();
}
}
releaseNativeResourcesInternal();
}
public SecretKey getKey(SecretKey parent, long mech, boolean temporary) throws Exception {
SecretKeyFactory skf = SecretKeyFactory.getInstance(parent.getAlgorithm(), "Mozilla-JSS");
SecretKey translated = skf.translateKey(parent);
SymmetricKey unwrapped = null;
if (translated instanceof SymmetricKey) {
unwrapped = (SymmetricKey) translated;
} else if (translated instanceof SecretKeyFacade) {
unwrapped = ((SecretKeyFacade) translated).key;
} else {
String msg = "Expected key to become an instance of ";
msg += "org.mozilla.jss.crypto.SymmetricKey or ";
msg += "org.mozilla.jss.crypto.SecretKeyFacade after ";
msg += "translation, but got: ";
msg += translated.getClass().getName();
throw new InvalidKeyException(msg);
}
SymmetricKey key = getKeyFromHandle(unwrapped, mech, temporary);
return new SecretKeyFacade(key);
}
private native SymmetricKey getKeyFromHandle(SymmetricKey parentKey, long mech, boolean temporary) throws Exception;
protected native void acquireNativeResourcesInternal() throws Exception;
protected native void releaseNativeResourcesInternal() throws Exception;
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/KBKDFFeedbackParams.java 0000664 0000000 0000000 00000010547 14565430767 0026530 0 ustar 00root root 0000000 0000000 package org.mozilla.jss.crypto;
import java.util.Arrays;
import org.mozilla.jss.pkcs11.PKCS11Constants;
public class KBKDFFeedbackParams extends KBKDFParameterSpec {
private byte[] initial_value;
public KBKDFFeedbackParams() {
}
public void setInitialValue(byte[] iv) throws IllegalArgumentException {
if (iv == null) {
String msg = "Expected non-null initial value!";
throw new IllegalArgumentException(msg);
}
this.initial_value = Arrays.copyOf(iv, iv.length);
}
/**
* Zero out the copiend contents of the initial value.
*
* Call this method when the contents of the initial value are sensitive
* and they're done being used. Note that this isn't called during
* close() as a given KBKDFParameterSpec instance may be reused, updating
* relevant parameters between calls.
*/
public void zeroInitialValue() {
if (initial_value == null) {
return;
}
for (int i = 0; i < initial_value.length; i++) {
initial_value[i] = 0;
}
}
@Override
protected void validateParameters() throws IllegalArgumentException {
if (prfKey == null) {
String msg = "Required parameter KDF key was never set.";
throw new IllegalArgumentException(msg);
}
if (prf != PKCS11Constants.CKM_SHA_1_HMAC &&
prf != PKCS11Constants.CKM_SHA256_HMAC &&
prf != PKCS11Constants.CKM_SHA384_HMAC &&
prf != PKCS11Constants.CKM_SHA512_HMAC &&
prf != PKCS11Constants.CKM_AES_CMAC) {
String msg = "Expected Pseudo-Random Function to be SHA1-HMAC, ";
msg += "SHA2-HMAC, or AES-CMAC, but got unknown PKCS#11 ";
msg += "constant: " + prf;
throw new IllegalArgumentException(msg);
}
if (params == null || params.length == 0) {
String msg = "Expected non-null, non-zero length array of KDF ";
msg += "parameters.";
throw new IllegalArgumentException(msg);
}
int index = 0;
for (KBKDFDataParameter param : params) {
if (param instanceof KBKDFOptionalCounterParam) {
KBKDFOptionalCounterParam kocp = (KBKDFOptionalCounterParam) param;
if (kocp.widthInBits == -1) {
String msg = "Got unexpected data in KBKDF Optional ";
msg += "Counter Parameter at index " + index + ": ";
msg += "Expected valid counter specification, but got ";
msg += "widthInBits of -1. Call setCounterSpec(...) ";
msg += "before using this parameter.";
throw new IllegalArgumentException(msg);
}
}
if (param instanceof KBKDFIterationVariableParam) {
KBKDFIterationVariableParam kivp = (KBKDFIterationVariableParam) param;
if (kivp.widthInBits != -1) {
String msg = "Got unexpected data in KBKDF Iteration ";
msg += "Variable Parameter at index " + index + ": ";
msg += "Expected empty counter specification, but got ";
msg += "widthInBits of " + kivp.widthInBits + ". Call ";
msg += "the no argument constructor instead to use this ";
msg += "parameter.";
throw new IllegalArgumentException(msg);
}
}
if (param instanceof KBKDFDKMLengthParam) {
KBKDFDKMLengthParam kdlp = (KBKDFDKMLengthParam) param;
if (kdlp.widthInBits == 0) {
String msg = "Got unexpected data in KBKDF DKM Length ";
msg += "Parameter at index " + index + ": Expected valid ";
msg += "length specification, but got widthInBits of 0. ";
msg += "Call setLngthSpec(...) before using this ";
msg += "parameter.";
throw new IllegalArgumentException(msg);
}
}
// Nothing to validate for byte array parameters.
index += 1;
}
}
@Override
protected native void acquireNativeResourcesInternal() throws Exception;
@Override
protected native void releaseNativeResourcesInternal() throws Exception;
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/KBKDFIterationVariableParam.java 0000664 0000000 0000000 00000003453 14565430767 0030263 0 ustar 00root root 0000000 0000000 package org.mozilla.jss.crypto;
import org.mozilla.jss.pkcs11.PKCS11Constants;
/**
* A KBKDF Iteration Variable Parameter is a type of KBKDF Data Parameter that
* either references the counter variable or otherwise is a pointer to the
* output of the previous PRF invocation.
*
* Note that in when used with Counter Mode KBKDF, this parameter must be
* initialized with the two argument constructor. In other KBKDF modes,
* in particular, Feedback and Pipeline modes, this must be initialized with
* the no argument constructor. To add an optional counter to the PRF input
* stream under Feedback and Pipeline modes, use KBKDFOptionalCounterParam
* instead.
*/
public class KBKDFIterationVariableParam extends KBKDFDataParameter {
protected boolean littleEndian = false;
protected long widthInBits = -1;
public KBKDFIterationVariableParam() {
super(PKCS11Constants.CK_SP800_108_ITERATION_VARIABLE);
}
public KBKDFIterationVariableParam(boolean littleEndian, long widthInBits) throws IllegalArgumentException {
this();
setCounterSpec(littleEndian, widthInBits);
}
public void setCounterSpec(boolean littleEndian, long widthInBits) throws IllegalArgumentException {
if (widthInBits < 8 || widthInBits > 64) {
throw new IllegalArgumentException("Expected to have width between 8 and 64, but was " + widthInBits);
}
if ((widthInBits % 8) != 0) {
throw new IllegalArgumentException("Expected width to be an even number of bytes, but was " + widthInBits);
}
this.littleEndian = littleEndian;
this.widthInBits = widthInBits;
}
@Override
protected native void acquireNativeResources() throws Exception;
@Override
protected native void releaseNativeResources() throws Exception;
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/KBKDFOptionalCounterParam.java 0000664 0000000 0000000 00000002656 14565430767 0030010 0 ustar 00root root 0000000 0000000 package org.mozilla.jss.crypto;
import org.mozilla.jss.pkcs11.PKCS11Constants;
/**
* A KBKDF Optional Counter Parameter is a type of KBKDF Data Parameter that
* describes the optional counter variable for Feedback and Pipeline KBKDFs.
*
* Note that this parameter is illegal in Counter Mode.
*/
public class KBKDFOptionalCounterParam extends KBKDFDataParameter {
protected boolean littleEndian = false;
protected long widthInBits = 0;
public KBKDFOptionalCounterParam() {
super(PKCS11Constants.CK_SP800_108_OPTIONAL_COUNTER);
}
public KBKDFOptionalCounterParam(boolean littleEndian, long widthInBits) throws IllegalArgumentException {
this();
setCounterSpec(littleEndian, widthInBits);
}
public void setCounterSpec(boolean littleEndian, long widthInBits) throws IllegalArgumentException {
if (widthInBits < 8 || widthInBits > 64) {
throw new IllegalArgumentException("Expected to have width between 8 and 64, but was " + widthInBits);
}
if ((widthInBits % 8) != 0) {
throw new IllegalArgumentException("Expected width to be an even number of bytes, but was " + widthInBits);
}
this.littleEndian = littleEndian;
this.widthInBits = widthInBits;
}
@Override
protected native void acquireNativeResources() throws Exception;
@Override
protected native void releaseNativeResources() throws Exception;
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/KBKDFParameterSpec.java 0000664 0000000 0000000 00000017362 14565430767 0026435 0 ustar 00root root 0000000 0000000 package org.mozilla.jss.crypto;
import java.security.InvalidKeyException;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.KeySpec;
import java.util.ArrayList;
import java.util.Arrays;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import org.mozilla.jss.pkcs11.PK11SymKey;
import org.mozilla.jss.util.NativeEnclosure;
public abstract class KBKDFParameterSpec extends NativeEnclosure implements AlgorithmParameterSpec, KeySpec {
/* Need access from outside; no real protections in setters outside
* of additional input types. */
public PK11SymKey prfKey;
public long derivedKeyAlgorithm;
public int keySize;
protected long prf;
protected KBKDFDataParameter[] params;
protected KBKDFDerivedKey[] additional_keys;
/**
* Set the underlying pseudo-random function from a PKCS11Algorithm enum
* value.
*/
public void setPRF(PKCS11Algorithm prf) throws IllegalArgumentException {
this.prf = prf.getValue();
}
/**
* Set the underlying pseudo-random function from a DigestAlgorithm
* (HMACAlgorithm or CMACAlgorithm) instance.
*/
public void setPRF(DigestAlgorithm prf) throws IllegalArgumentException {
if (!(prf instanceof HMACAlgorithm) && !(prf instanceof CMACAlgorithm)) {
String msg = "Unknown pseudo-random function type: expected ";
msg += "either HMAC or CMAC algorithms. Got: ";
msg += prf.getClass().getName();
throw new IllegalArgumentException(msg);
}
this.prf = prf.getEnum().getValue();
}
/**
* Set the underlying pseudo-random function from a PKCS#11 constant;
* see org.mozilla.jss.pkcs11.PKCS11Constants for permitted values.
*/
public void setPRF(long prf) {
this.prf = prf;
}
/**
* Set the base key used with the underlying PRF.
*
* Must be importable to a JSS SymmetricKey or SecretKeyFacade.
*/
public void setPRFKey(SecretKey key) throws InvalidKeyException {
if (key instanceof PK11SymKey) {
prfKey = (PK11SymKey) key;
return;
}
if (key instanceof SecretKeyFacade) {
setPRFKey(((SecretKeyFacade) key).key);
return;
}
try {
SecretKeyFactory skf = SecretKeyFactory.getInstance(key.getAlgorithm(), "Mozilla-JSS");
SecretKey translated = skf.translateKey(key);
if (translated instanceof SymmetricKey) {
setPRFKey(translated);
return;
}
if (translated instanceof SecretKeyFacade) {
setPRFKey(((SecretKeyFacade) translated).key);
return;
}
String msg = "Expected key to become an instance of ";
msg += "org.mozilla.jss.crypto.SymmetricKey or ";
msg += "org.mozilla.jss.crypto.SecretKeyFacade after ";
msg += "translation, but got: ";
msg += translated.getClass().getName();
throw new InvalidKeyException(msg);
} catch (Exception excep) {
throw new InvalidKeyException("Unable to import key: " + excep.getMessage(), excep);
}
}
/**
* Set the algorithm for the derived key from a PKCS11Algorithm enum value.
*/
public void setDerivedKeyAlgorithm(PKCS11Algorithm algo) throws IllegalArgumentException {
if (algo == null) {
String msg = "Expected non-null PKCS11Algorithm value, but was null.";
throw new IllegalArgumentException(msg);
}
derivedKeyAlgorithm = algo.getValue();
}
/**
* Sets the algorithm for the derived key from a PKCS#11 value; see
* org.mozilla.jss.pkcs11.PKCS11Constants for constant values.
*/
public void setDerivedKeyAlgorithm(long algo) throws IllegalArgumentException {
derivedKeyAlgorithm = algo;
}
/**
* Set the size of the derived key.
*
* If zero, will attempt to use the derived key algorithm's default key
* size.
*/
public void setKeySize(int keySize) {
this.keySize = keySize;
}
/**
* Set parameters for key derivation.
*
* This overwrites all existing parameters. Note that params cannot be
* NULL.
*/
public void setParameters(KBKDFDataParameter[] params) throws IllegalArgumentException {
if (params == null) {
String msg = "Expected populated array of KBKDFDataParameters, ";
msg += "but was null.";
throw new IllegalArgumentException(msg);
}
this.params = params;
}
/**
* Appends (to the end) a new data parameter.
*/
public void addParameter(KBKDFDataParameter param) throws IllegalArgumentException {
if (param == null) {
String msg = "Expected non-null instance of KBKDFDataParameters, ";
msg += "but was null.";
throw new IllegalArgumentException(msg);
}
ArrayList data_params;
if (this.params == null) {
data_params = new ArrayList<>(1);
} else {
data_params = new ArrayList<>(Arrays.asList(this.params));
}
data_params.add(param);
this.params = data_params.toArray(new KBKDFDataParameter[data_params.size()]);
}
/**
* Set an array of additional derived keys.
*/
public void setAdditionalDerivedKeys(KBKDFDerivedKey[] additional_keys) throws IllegalArgumentException {
if (additional_keys == null) {
String msg = "Expected populated array of KBKDFDerivedKey, ";
msg += "but was null.";
throw new IllegalArgumentException(msg);
}
this.additional_keys = additional_keys;
}
/**
* Append (to the end) a new derived key.
*/
public void addAdditionalDerivedKey(KBKDFDerivedKey derived_key) throws IllegalArgumentException {
if (derived_key == null) {
String msg = "Expected non-null instance of KBKDFDerivedKey, ";
msg += "but was null.";
throw new IllegalArgumentException(msg);
}
ArrayList keys;
if (additional_keys == null) {
keys = new ArrayList<>(1);
} else {
keys = new ArrayList<>(Arrays.asList(additional_keys));
}
keys.add(derived_key);
additional_keys = keys.toArray(new KBKDFDerivedKey[keys.size()]);
}
@Override
protected void acquireNativeResources() throws Exception {
validateParameters();
if (params != null) {
for (KBKDFDataParameter param : params) {
param.open();
}
}
if (additional_keys != null) {
for (KBKDFDerivedKey key : additional_keys) {
key.open();
}
}
acquireNativeResourcesInternal();
}
@Override
protected void releaseNativeResources() throws Exception {
if (additional_keys != null) {
for (KBKDFDerivedKey key : additional_keys) {
key.close();
}
}
if (params != null) {
for (KBKDFDataParameter param : params) {
param.close();
}
}
releaseNativeResourcesInternal();
}
protected abstract void acquireNativeResourcesInternal() throws Exception;
protected abstract void releaseNativeResourcesInternal() throws Exception;
/**
* Validate all class members prior to acquiring native resources.
*
* This is implemented by the derived KBKDF modes in an effort to give
* useful exceptions before derivation, instead of vague errors during
* derivation.
*/
protected abstract void validateParameters() throws IllegalArgumentException;
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/KBKDFPipelineParams.java 0000664 0000000 0000000 00000006721 14565430767 0026610 0 ustar 00root root 0000000 0000000 package org.mozilla.jss.crypto;
import org.mozilla.jss.pkcs11.PKCS11Constants;
public class KBKDFPipelineParams extends KBKDFParameterSpec {
public KBKDFPipelineParams() {
}
@Override
protected void validateParameters() throws IllegalArgumentException {
if (prfKey == null) {
String msg = "Required parameter KDF key was never set.";
throw new IllegalArgumentException(msg);
}
if (prf != PKCS11Constants.CKM_SHA_1_HMAC &&
prf != PKCS11Constants.CKM_SHA256_HMAC &&
prf != PKCS11Constants.CKM_SHA384_HMAC &&
prf != PKCS11Constants.CKM_SHA512_HMAC &&
prf != PKCS11Constants.CKM_AES_CMAC) {
String msg = "Expected Pseudo-Random Function to be SHA1-HMAC, ";
msg += "SHA2-HMAC, or AES-CMAC, but got unknown PKCS#11 ";
msg += "constant: " + prf;
throw new IllegalArgumentException(msg);
}
if (params == null || params.length == 0) {
String msg = "Expected non-null, non-zero length array of KDF ";
msg += "parameters.";
throw new IllegalArgumentException(msg);
}
int index = 0;
for (KBKDFDataParameter param : params) {
if (param instanceof KBKDFOptionalCounterParam) {
KBKDFOptionalCounterParam kocp = (KBKDFOptionalCounterParam) param;
if (kocp.widthInBits == -1) {
String msg = "Got unexpected data in KBKDF Optional ";
msg += "Counter Parameter at index " + index + ": ";
msg += "Expected valid counter specification, but got ";
msg += "widthInBits of -1. Call setCounterSpec(...) ";
msg += "before using this parameter.";
throw new IllegalArgumentException(msg);
}
}
if (param instanceof KBKDFIterationVariableParam) {
KBKDFIterationVariableParam kivp = (KBKDFIterationVariableParam) param;
if (kivp.widthInBits != -1) {
String msg = "Got unexpected data in KBKDF Iteration ";
msg += "Variable Parameter at index " + index + ": ";
msg += "Expected empty counter specification, but got ";
msg += "widthInBits of " + kivp.widthInBits + ". Call ";
msg += "the no argument constructor instead to use this ";
msg += "parameter.";
throw new IllegalArgumentException(msg);
}
}
if (param instanceof KBKDFDKMLengthParam) {
KBKDFDKMLengthParam kdlp = (KBKDFDKMLengthParam) param;
if (kdlp.widthInBits == 0) {
String msg = "Got unexpected data in KBKDF DKM Length ";
msg += "Parameter at index " + index + ": Expected valid ";
msg += "length specification, but got widthInBits of 0. ";
msg += "Call setLngthSpec(...) before using this ";
msg += "parameter.";
throw new IllegalArgumentException(msg);
}
}
// Nothing to validate for byte array parameters.
index += 1;
}
}
@Override
protected native void acquireNativeResourcesInternal() throws Exception;
@Override
protected native void releaseNativeResourcesInternal() throws Exception;
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/KeyAlreadyImportedException.java 0000664 0000000 0000000 00000001615 14565430767 0030547 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.crypto;
/**
* This exception is thrown if the user tries to import a
* key which is already in the specified token
*/
public class KeyAlreadyImportedException extends java.lang.Exception {
private static final long serialVersionUID = 1L;
public KeyAlreadyImportedException() {}
public KeyAlreadyImportedException(String mesg) {
super(mesg);
}
public KeyAlreadyImportedException(String mesg, Throwable cause) {
super(mesg, cause);
}
public KeyAlreadyImportedException(String mesg, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(mesg, cause, enableSuppression, writableStackTrace);
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/KeyGenAlgorithm.java 0000664 0000000 0000000 00000022070 14565430767 0026161 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.crypto;
import java.security.NoSuchAlgorithmException;
import java.util.Hashtable;
import org.mozilla.jss.asn1.OBJECT_IDENTIFIER;
/**
* Algorithms that can be used for generating symmetric keys.
*/
public class KeyGenAlgorithm extends Algorithm {
protected static interface KeyStrengthValidator {
public boolean isValidKeyStrength(int strength);
}
protected static class FixedKeyStrengthValidator
implements KeyStrengthValidator {
private int strength;
public FixedKeyStrengthValidator(int strength) {
this.strength = strength;
}
@Override
public boolean isValidKeyStrength(int strength) {
return this.strength == strength;
}
}
protected static class AnyKeyStrengthValidator
implements KeyStrengthValidator {
@Override
public boolean isValidKeyStrength(int strength) {
return true;
}
}
protected KeyGenAlgorithm(int oidTag, String name,
KeyStrengthValidator keyStrengthValidator,
OBJECT_IDENTIFIER oid, Class> paramClass) {
super(oidTag, name, oid, paramClass);
this.keyStrengthValidator = keyStrengthValidator;
if (oid != null) {
oidMap.put(oid, this);
}
}
///////////////////////////////////////////////////////////////////////
// OIDs
///////////////////////////////////////////////////////////////////////
private static final OBJECT_IDENTIFIER PKCS5 = OBJECT_IDENTIFIER.PKCS5;
private static final OBJECT_IDENTIFIER PKCS12_PBE = OBJECT_IDENTIFIER.PKCS12.subBranch(1);
///////////////////////////////////////////////////////////////////////
// OID mapping
///////////////////////////////////////////////////////////////////////
private static Hashtable oidMap = new Hashtable<>();
public static KeyGenAlgorithm fromOID(OBJECT_IDENTIFIER oid)
throws NoSuchAlgorithmException {
Object alg = oidMap.get(oid);
if (alg == null) {
throw new NoSuchAlgorithmException(oid.toString());
} else {
return (KeyGenAlgorithm) alg;
}
}
private KeyStrengthValidator keyStrengthValidator;
/**
* @param strength Key strength.
* @return true
if the given strength is valid for this
* key generation algorithm. Note that PBE algorithms require
* PBEParameterSpecs rather than strengths. It is the responsibility
* of the caller to verify this.
*/
public boolean isValidStrength(int strength) {
return keyStrengthValidator.isValidKeyStrength(strength);
}
//////////////////////////////////////////////////////////////
public static final KeyGenAlgorithm GENERIC_SECRET = new KeyGenAlgorithm(
CKM_GENERIC_SECRET_KEY_GEN,
"GenericSecret",
new AnyKeyStrengthValidator(),
null,
null);
//////////////////////////////////////////////////////////////
public static final KeyGenAlgorithm DES = new KeyGenAlgorithm(
CKM_DES_KEY_GEN,
"DES",
new FixedKeyStrengthValidator(56),
null,
null);
//////////////////////////////////////////////////////////////
public static final KeyGenAlgorithm DES3 = new KeyGenAlgorithm(
CKM_DES3_KEY_GEN,
"DESede",
new FixedKeyStrengthValidator(168),
null,
null);
public static final KeyGenAlgorithm DESede = DES3;
//////////////////////////////////////////////////////////////
public static final KeyGenAlgorithm RC4 = new KeyGenAlgorithm(
CKM_RC4_KEY_GEN,
"RC4",
new AnyKeyStrengthValidator(),
null,
null);
//////////////////////////////////////////////////////////////
@Deprecated(since="5.0.1", forRemoval=true)
public static final KeyGenAlgorithm PBA_SHA1_HMAC = new KeyGenAlgorithm(
CKM_PBA_SHA1_WITH_SHA1_HMAC,
"PBA/SHA1/HMAC",
new FixedKeyStrengthValidator(160),
null,
PBEKeyGenParams.class);
public static final KeyGenAlgorithm PBE_SHA256_HMAC = new KeyGenAlgorithm(
SEC_OID_SHA256,
"PBE/SHA256/HMAC",
new AnyKeyStrengthValidator(),
null,
PBEKeyGenParams.class);
public static final KeyGenAlgorithm PBE_SHA384_HMAC = new KeyGenAlgorithm(
SEC_OID_SHA384,
"PBE/SHA384/HMAC",
new AnyKeyStrengthValidator(),
null,
PBEKeyGenParams.class);
public static final KeyGenAlgorithm PBE_SHA512_HMAC = new KeyGenAlgorithm(
SEC_OID_SHA512,
"PBE/SHA512/HMAC",
new AnyKeyStrengthValidator(),
null,
PBEKeyGenParams.class);
@Deprecated(since="5.0.1", forRemoval=true)
public static final KeyGenAlgorithm SHA1_HMAC = new KeyGenAlgorithm(
CKM_SHA_1_HMAC,
"SHA1/HMAC",
new FixedKeyStrengthValidator(160),
null,
null);
public static final KeyGenAlgorithm SHA256_HMAC = new KeyGenAlgorithm(
CKM_SHA256_HMAC,
"SHA256/HMAC",
new FixedKeyStrengthValidator(256),
null,
null);
public static final KeyGenAlgorithm SHA384_HMAC = new KeyGenAlgorithm(
CKM_SHA384_HMAC,
"SHA384/HMAC",
new FixedKeyStrengthValidator(384),
null,
null);
public static final KeyGenAlgorithm SHA512_HMAC = new KeyGenAlgorithm(
CKM_SHA512_HMAC,
"SHA512/HMAC",
new FixedKeyStrengthValidator(512),
null,
null);
//////////////////////////////////////////////////////////////
public static final KeyGenAlgorithm AES = new KeyGenAlgorithm(
CKM_AES_KEY_GEN,
"AES",
new KeyStrengthValidator() {
@Override
public boolean isValidKeyStrength(int strength) {
return strength == 128 || strength == 192 || strength == 256;
}
},
null,
null);
//////////////////////////////////////////////////////////////
public static final KeyGenAlgorithm RC2 = new KeyGenAlgorithm(
CKM_RC2_KEY_GEN,
"RC2",
new KeyStrengthValidator() {
@Override
public boolean isValidKeyStrength(int strength) {
// Allow any key of size between 1 byte and 128 bytes
return strength >= 8 && strength <= (128 * 8);
}
},
null,
null);
//////////////////////////////////////////////////////////////
/////////////// GENERIC KBKDFs: NIST SP800-108 ///////////////
//////////////////////////////////////////////////////////////
public static final KeyGenAlgorithm SP800_108_COUNTER_KDF = new KeyGenAlgorithm(
CKM_SP800_108_COUNTER_KDF,
"SP800_108_COUNTER_KDF",
new AnyKeyStrengthValidator(),
null,
KBKDFCounterParams.class);
public static final KeyGenAlgorithm SP800_108_FEEDBACK_KDF = new KeyGenAlgorithm(
CKM_SP800_108_FEEDBACK_KDF,
"SP800_108_FEEDBACK_KDF",
new AnyKeyStrengthValidator(),
null,
KBKDFFeedbackParams.class);
public static final KeyGenAlgorithm SP800_108_DOUBLE_PIPELINE_KDF = new KeyGenAlgorithm(
CKM_SP800_108_DOUBLE_PIPELINE_KDF,
"SP800_108_DOUBLE_PIPELINE_KDF",
new AnyKeyStrengthValidator(),
null,
KBKDFPipelineParams.class);
//////////////////////////////////////////////////////////////
//////////// Data KBKDFs: NSS-only NIST SP800-108 ////////////
//////////////////////////////////////////////////////////////
public static final KeyGenAlgorithm NSS_SP800_108_COUNTER_KDF_DERIVE_DATA = new KeyGenAlgorithm(
CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA,
"NSS_SP800_108_COUNTER_KDF_DERIVE_DATA",
new AnyKeyStrengthValidator(),
null,
KBKDFCounterParams.class);
public static final KeyGenAlgorithm NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA = new KeyGenAlgorithm(
CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA,
"NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA",
new AnyKeyStrengthValidator(),
null,
KBKDFFeedbackParams.class);
public static final KeyGenAlgorithm NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA = new KeyGenAlgorithm(
CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA,
"NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA",
new AnyKeyStrengthValidator(),
null,
KBKDFPipelineParams.class);
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/KeyGenerator.java 0000664 0000000 0000000 00000012053 14565430767 0025527 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.crypto;
import java.io.CharConversionException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.spec.AlgorithmParameterSpec;
/**
* Generates symmetric keys for encryption and decryption.
*/
public interface KeyGenerator {
/**
* @param strength Key size in bits. Must be evenly divisible by 8.
* @throws InvalidAlgorithmParameterException If parameter is invalid.
*/
public void initialize(int strength)
throws InvalidAlgorithmParameterException;
public void initialize(AlgorithmParameterSpec parameters)
throws InvalidAlgorithmParameterException;
/**
* @param usages The operations the key will be used for after it is
* generated. You have to specify these so that the key can be properly
* marked with the operations it supports. Some PKCS #11 tokens require
* that a key be marked for an operation before it can perform that
* operation. The default is SymmetricKey.Usage.SIGN and
* SymmetricKey.Usage.ENCRYPT.
*/
public void setKeyUsages(SymmetricKey.Usage[] usages);
/**
* Tells the generator to generate temporary or permanent keys.
* Temporary keys are not written permanently to the token. They
* are destroyed by the garbage collector. If this method is not
* called, the default is temporary keys.
* @param temp True to generate temporary key.
*/
public void temporaryKeys(boolean temp);
/**
* Tells the generator to generate sensitive or insensitive keys.
* Certain attributes of a sensitive key cannot be revealed in
* plaintext outside the token. If this method is not called, the
* default is token dependent.
* @param sensitive True to generate sensitive.
*/
public void sensitiveKeys(boolean sensitive);
/**
* Generates a symmetric key.
* @return Symmetric key.
* @throws IllegalStateException If key generation failed.
* @throws TokenException If an error occurred in the token.
* @throws CharConversionException If an encoding error occurred.
*/
public SymmetricKey generate()
throws IllegalStateException, TokenException, CharConversionException;
/**
* Generates an Initialization Vector using a PBE algorithm.
* In order to call this method, the algorithm must be a PBE algorithm,
* and the KeyGenerator must have been initialized with an instance
* of PBEKeyGenParams
.
*
* @return The initialization vector derived from the password and salt
* using the PBE algorithm.
* @exception IllegalStateException If the algorithm is not a PBE
* algorithm, or the KeyGenerator has not been initialized with
* an instance of PBEKeyGenParams
.
* @exception TokenException If an error occurs on the CryptoToken while
* generating the IV.
* @exception CharConversionException If an encoding error occurred.
*/
public byte[] generatePBE_IV()
throws IllegalStateException, TokenException, CharConversionException;
/**
* Allows a SymmetricKey to be cloned on a different token.
*
* @param key Symmetric key.
* @return Cloned symmetric key.
* @exception SymmetricKey.NotExtractableException If the key material
* cannot be extracted from the current token.
* @exception InvalidKeyException If the owning token cannot process
* the key to be cloned.
* @exception TokenException If an error occurred in the token.
*/
public SymmetricKey clone(SymmetricKey key)
throws SymmetricKey.NotExtractableException,
InvalidKeyException, TokenException;
/**
* An interface for converting a password of Java characters into an array
* of bytes. This conversion must be performed to provide a byte array
* to the low-level crypto engine. The default conversion is UTF8.
* Null-termination is not necessary, and indeed is usually incorrect,
* since the password is passed to the crypto engine as a byte array, not
* a C string.
*/
public static interface CharToByteConverter {
/**
* Converts a password of Java characters into a password of
* bytes, using some encoding scheme. The input char array must
* not be modified.
* @param chars Password characters.
* @return Password as byte array.
* @throws CharConversionException If an error occurred.
*/
public byte[] convert(char[] chars) throws CharConversionException;
}
/**
* Sets the character to byte converter for passwords. The default
* conversion is UTF8 with no null termination.
* @param charToByte Character-to-byte converter.
*/
public void setCharToByteConverter(CharToByteConverter charToByte);
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/KeyPairAlgorithm.java 0000664 0000000 0000000 00000005657 14565430767 0026357 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.crypto;
import java.security.NoSuchAlgorithmException;
import java.util.Hashtable;
/**
* Algorithms that can be used for keypair generation.
*/
public class KeyPairAlgorithm extends Algorithm {
protected KeyPairAlgorithm(int oidIndex, String name, Algorithm algFamily) {
super(oidIndex, name);
this.algFamily = algFamily;
nameMap.put(name, this);
}
/**
* Returns the algorithm family for a given key pair generation algorithm.
* If a token supports a family and is writable, we can do keypair gen
* on the token even if it doesn't support the keypair gen algorithm.
* We do this by doing the keypair gen on the internal module and then
* moving the key out to the other token.
* @return Algorithm family.
*/
public Algorithm
getAlgFamily()
{
return algFamily;
}
private static Hashtable nameMap = new Hashtable<>();
/**
* Looks up a key pair generation algorithm from its name. The names
* are those specified in the JCA spec. For example, "RSA" and "DSA".
*
* @param algName Algorithm name.
* @return Key pair generation algorithm.
* @throws NoSuchAlgorithmException If the name of the algorithm is not
* recognized as a supported algorithm.
*/
public static KeyPairAlgorithm fromString(String algName)
throws NoSuchAlgorithmException
{
KeyPairAlgorithm alg = nameMap.get(algName);
if( alg == null ) {
throw new NoSuchAlgorithmException();
}
return alg;
}
protected Algorithm algFamily;
////////////////////////////////////////////////////////////////
// Key-Pair Generation Algorithms
////////////////////////////////////////////////////////////////
public static final Algorithm
RSAFamily = new Algorithm(SEC_OID_PKCS1_RSA_ENCRYPTION, "RSA");
public static final Algorithm
DSAFamily = new Algorithm(SEC_OID_ANSIX9_DSA_SIGNATURE, "DSA");
public static final Algorithm
// To support both ECDSA and ECDH, it is best to provide two EC Families;
// However, since there is no token that does only CKM_DERIVE to
// date, we will just do ECDSA for now as it is sufficient enough today.
// This fix will support tokens that do not do ECDH
ECFamily = new Algorithm(SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST, "EC");
public static final KeyPairAlgorithm
RSA = new KeyPairAlgorithm(CKM_RSA_PKCS_KEY_PAIR_GEN, "RSA", RSAFamily);
public static final KeyPairAlgorithm
DSA = new KeyPairAlgorithm(CKM_DSA_KEY_PAIR_GEN, "DSA", DSAFamily);
public static final KeyPairAlgorithm
EC = new KeyPairAlgorithm(CKM_EC_KEY_PAIR_GEN, "EC", ECFamily);
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/KeyPairGenerator.java 0000664 0000000 0000000 00000015171 14565430767 0026347 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.crypto;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidParameterException;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
/**
* Generates RSA and DSA key pairs. Each CryptoToken provides a
* KeyPairGenerator, which can be used to generate key pairs on that token.
* A given token may not support all algorithms, and some tokens may not
* support any key pair generation. If a token does not support key pair
* generation, the Netscape internal token may do it instead. Call
* keygenOnInternalToken
to find out if this is happening.
*
* @see org.mozilla.jss.crypto.CryptoToken#getKeyPairGenerator
*/
public class KeyPairGenerator {
/**
* Creates a new key pair generator. KeyPairGenerators should
* be obtained by calling CryptoToken.getKeyPairGenerator
* instead of calling this constructor.
*
* @param algorithm The type of keys that the generator will be
* used to generate.
* @param engine The engine object that provides the implementation for
* the class.
*/
public KeyPairGenerator(KeyPairAlgorithm algorithm,
KeyPairGeneratorSpi engine) {
this.algorithm = algorithm;
this.engine = engine;
}
/**
* Generates a new key pair.
*
* @return A new key pair. The keys reside on the CryptoToken that
* provided this KeyPairGenerator
.
* @exception TokenException If an error occurs on the CryptoToken
* in the process of generating the key pair.
*/
public java.security.KeyPair
genKeyPair() throws TokenException {
return engine.generateKeyPair();
}
/**
* @return The type of key that this generator generates.
*/
public KeyPairAlgorithm getAlgorithm() {
return algorithm;
}
/**
* Initializes the generator with algorithm-specific parameters.
* The SecureRandom
parameters is ignored.
*
* @param params Algorithm-specific parameters for the key pair generation.
* @param random This parameter is ignored. NSS does not accept
* an external source of random numbers.
* @exception InvalidAlgorithmParameterException If the parameters are
* inappropriate for the type of key pair that is being generated,
* or they are not supported by this generator.
* @see java.security.spec.RSAKeyGenParameterSpec
* @see java.security.spec.DSAParameterSpec
*/
public void initialize(AlgorithmParameterSpec params, SecureRandom random)
throws InvalidAlgorithmParameterException
{
engine.initialize(params, random);
}
/**
* Initializes the generator with algorithm-specific parameters.
*
* @param params Algorithm-specific parameters for the key pair generation.
* @exception InvalidAlgorithmParameterException If the parameters are
* inappropriate for the type of key pair that is being generated,
* or they are not supported by this generator.
* @see java.security.spec.RSAKeyGenParameterSpec
* @see java.security.spec.DSAParameterSpec
*/
public void initialize(AlgorithmParameterSpec params)
throws InvalidAlgorithmParameterException
{
engine.initialize(params, null);
}
/**
* Initializes the generator with the strength of the keys.
* The SecureRandom
parameter is ignored.
*
* @param strength The strength of the keys that will be generated.
* Usually this is the length of the key in bits.
* @param random This parameter is ignored. NSS does not accept
* an external source of random numbers.
*/
public void initialize(int strength, SecureRandom random) {
engine.initialize(strength, random);
}
/**
* Initializes the generator with the strength of the keys.
*
* @param strength The strength of the keys that will be generated.
* Usually this is the length of the key in bits.
*/
public void initialize(int strength) {
engine.initialize(strength, null);
}
/**
* @return true if the keypair generation will take place on the
* internal token rather than the current token. This will
* happen if the token does not support keypair generation
* but does support this algorithm and is writable. In this
* case the keypair will be generated on the Netscape internal
* token and then moved to this token.
*/
public boolean keygenOnInternalToken() {
return engine.keygenOnInternalToken();
}
/**
* Tells the generator to generate temporary or permanent keypairs.
* Temporary keys are not written permanently to the token. They
* are destroyed by the garbage collector. If this method is not
* called, the default is permanent keypairs.
* @param temp True to generate temporary keypairs.
*/
public void temporaryPairs(boolean temp) {
engine.temporaryPairs(temp);
}
/**
* Tells the generator to generate sensitive or insensitive keypairs.
* Certain attributes of a sensitive key cannot be revealed in
* plaintext outside the token. If this method is not called, the
* default depends on the temporaryPairs mode for backward
* compatibility. The default is sensitive keypairs if the
* temporaryPairs mode is false, or insensitive keypairs if the
* temporaryPairs mode is true.
* @param sensitive To generate sensitive keypairs.
*/
public void sensitivePairs(boolean sensitive) {
engine.sensitivePairs(sensitive);
}
/**
* Tells the generator to generate extractable or unextractable
* keypairs. Extractable keys can be extracted from the token after
* wrapping. If this method is not called, the default is token
* dependent.
* @param extractable True to generate extractable keypairs.
*/
public void extractablePairs(boolean extractable) {
engine.extractablePairs(extractable);
}
public void setKeyPairUsages(KeyPairGeneratorSpi.Usage[] usages,
KeyPairGeneratorSpi.Usage[] usages_mask) {
engine.setKeyPairUsages(usages,usages_mask);
}
public int getCurveCodeByName(String curveName)
throws InvalidParameterException {
return engine.getCurveCodeByName(curveName);
}
protected KeyPairAlgorithm algorithm;
protected KeyPairGeneratorSpi engine;
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/KeyPairGeneratorSpi.java 0000664 0000000 0000000 00000005671 14565430767 0027027 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.crypto;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidParameterException;
import java.security.KeyPair;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
import org.mozilla.jss.pkcs11.PKCS11Constants;
public abstract class KeyPairGeneratorSpi {
public KeyPairGeneratorSpi() {
}
public abstract void initialize(int strength, SecureRandom random);
public abstract void initialize(AlgorithmParameterSpec params,
SecureRandom random)
throws InvalidAlgorithmParameterException;
public abstract KeyPair generateKeyPair() throws TokenException;
public abstract int getCurveCodeByName(String curveName) throws InvalidParameterException;
public abstract void temporaryPairs(boolean temp);
public abstract void sensitivePairs(boolean sensitive);
public abstract void extractablePairs(boolean extractable);
public abstract boolean keygenOnInternalToken();
/**
* In PKCS #11, each keypair can be marked with the operations it will
* be used to perform. Some tokens require that a key be marked for
* an operation before the key can be used to perform that operation;
* other tokens don't care. NSS provides a way to specify a set of
* flags and a corresponding mask for these flags. If a specific usage
* is desired set the value for that usage. If it is not set, let NSS
* behave in it's default fashion. If a behavior is desired, also set
* that behavior in the mask as well as the flags.
*
*/
public enum Usage {
ENCRYPT (PKCS11Constants.CKF_ENCRYPT),
DECRYPT (PKCS11Constants.CKF_DECRYPT),
SIGN (PKCS11Constants.CKF_SIGN),
SIGN_RECOVER (PKCS11Constants.CKF_SIGN_RECOVER),
VERIFY (PKCS11Constants.CKF_VERIFY),
VERIFY_RECOVER (PKCS11Constants.CKF_VERIFY_RECOVER),
WRAP (PKCS11Constants.CKF_WRAP),
UNWRAP (PKCS11Constants.CKF_UNWRAP),
DERIVE (PKCS11Constants.CKF_DERIVE);
private final long value;
Usage(long value) {
this.value = value;
}
/**
* @deprecated Use ordinal()
instead.
*/
@Deprecated
public int getVal() { return ordinal(); }
/**
* Get PKCS #11 CKF_ value.
*/
public long value() { return value; }
}
/**
* setKeyPairUsages
* @param usages Usages.
* @param usages_mask Usages mask.
*/
public abstract void setKeyPairUsages(KeyPairGeneratorSpi.Usage[] usages,
KeyPairGeneratorSpi.Usage[] usages_mask);
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/KeyWrapAlgorithm.java 0000664 0000000 0000000 00000014641 14565430767 0026366 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.crypto;
import java.security.NoSuchAlgorithmException;
import java.util.Hashtable;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.RC2ParameterSpec;
import javax.crypto.spec.OAEPParameterSpec;
import org.mozilla.jss.asn1.OBJECT_IDENTIFIER;
/**
*
*/
public class KeyWrapAlgorithm extends Algorithm {
protected KeyWrapAlgorithm(int oidTag, String name, Class> paramClass,
boolean padded, int blockSize) {
super(oidTag, name, null, paramClass);
this.padded = padded;
this.blockSize = blockSize;
if( name != null ) {
nameMap.put(name.toLowerCase(), this);
}
}
protected KeyWrapAlgorithm(int oidTag, String name, Class> []paramClasses,
boolean padded, int blockSize) {
super(oidTag, name, null, paramClasses);
this.padded = padded;
this.blockSize = blockSize;
if( name != null ) {
nameMap.put(name.toLowerCase(), this);
}
}
private boolean padded;
private int blockSize;
private static Hashtable nameMap = new Hashtable<>();
public static KeyWrapAlgorithm fromString(String name)
throws NoSuchAlgorithmException
{
Object alg = nameMap.get( name.toLowerCase() );
if( alg == null ) {
throw new NoSuchAlgorithmException();
} else {
return (KeyWrapAlgorithm) alg;
}
}
public boolean isPadded() {
return padded;
}
public int getBlockSize() {
return blockSize;
}
private static Class>[] IVParameterSpecClasses = null;
static {
IVParameterSpecClasses = new Class[2];
IVParameterSpecClasses[0] = IVParameterSpec.class;
IVParameterSpecClasses[1] = IvParameterSpec.class;
}
public static final KeyWrapAlgorithm
DES_ECB = new KeyWrapAlgorithm(SEC_OID_DES_ECB, "DES/ECB", (Class>) null,
false, 8);
public static final KeyWrapAlgorithm
DES_CBC = new KeyWrapAlgorithm(SEC_OID_DES_CBC, "DES/CBC",
IVParameterSpecClasses, false, 8);
public static final KeyWrapAlgorithm
DES_CBC_PAD = new KeyWrapAlgorithm(CKM_DES_CBC_PAD, "DES/CBC/Pad",
IVParameterSpecClasses, true, 8);
public static final KeyWrapAlgorithm
DES3_ECB = new KeyWrapAlgorithm(CKM_DES3_ECB, "DES3/ECB", (Class>)null,
false, 8);
public static final KeyWrapAlgorithm
DES3_CBC = new KeyWrapAlgorithm(SEC_OID_DES_EDE3_CBC, "DES3/CBC",
IVParameterSpecClasses, false, 8);
public static final KeyWrapAlgorithm
DES3_CBC_PAD = new KeyWrapAlgorithm(CKM_DES3_CBC_PAD, "DES3/CBC/Pad",
IVParameterSpecClasses, true, 8);
public static final KeyWrapAlgorithm
RSA = new KeyWrapAlgorithm(SEC_OID_PKCS1_RSA_ENCRYPTION, "RSA",
(Class>) null, false, 0);
public static final KeyWrapAlgorithm
RSA_OAEP = new KeyWrapAlgorithm(CKM_RSA_PKCS_OAEP, "RSAES-OAEP",
OAEPParameterSpec.class, true, 0);
public static final KeyWrapAlgorithm
PLAINTEXT = new KeyWrapAlgorithm(0, "Plaintext", (Class>) null,
false, 0);
public static final KeyWrapAlgorithm
AES_ECB = new KeyWrapAlgorithm(CKM_AES_ECB, "AES/ECB/NoPadding",
(Class>) null, false, 16);
public static final KeyWrapAlgorithm
AES_CBC = new KeyWrapAlgorithm(CKM_AES_CBC, "AES/CBC/NoPadding",
IVParameterSpecClasses, false, 16);
public static final KeyWrapAlgorithm
AES_CBC_PAD = new KeyWrapAlgorithm(CKM_AES_CBC_PAD, "AES/CBC/PKCS5Padding",
IVParameterSpecClasses, true, 16);
public static final KeyWrapAlgorithm
RC2_CBC_PAD = new KeyWrapAlgorithm(CKM_RC2_CBC_PAD, "RC2/CBC/PKCS5Padding",
RC2ParameterSpec.class, true, 8);
/*
* Note: AES_KEY_WRAP is not suitable for wrapping private keys;
* Use AES_KEY_WRAP_PAD instead
* Also note that although it is mapped to CKM_NSS_AES_KEY_WRAP_*
* here, down in PK11KeyWrapper.c, logic exists to map to
* CKM_AES_KEY_WRAP_* if it is determined to recognize the mechanism
*/
public static final KeyWrapAlgorithm
AES_KEY_WRAP = new KeyWrapAlgorithm(CKM_NSS_AES_KEY_WRAP, "AES KeyWrap/NoPadding",
(Class>) null, false, 8);
public static final KeyWrapAlgorithm
AES_KEY_WRAP_PAD = new KeyWrapAlgorithm(CKM_NSS_AES_KEY_WRAP_PAD, "AES KeyWrap/Padding",
(Class>) null, true, 8);
/*
* Added to support HSMs. There is no CKM_NSS equivalent, unlike the
* above two mechanisms.
*/
public static final KeyWrapAlgorithm
AES_KEY_WRAP_PAD_KWP = new KeyWrapAlgorithm(CKM_AES_KEY_WRAP_KWP, "AES KeyWrap/Wrapped",
(Class>) null, true, 8);
public static final OBJECT_IDENTIFIER AES_KEY_WRAP_PAD_OID = new OBJECT_IDENTIFIER("2.16.840.1.101.3.4.1.8");
public static final OBJECT_IDENTIFIER AES_KEY_WRAP_KWP_OID = new OBJECT_IDENTIFIER("2.16.840.1.101.3.4.1.8");
public static final OBJECT_IDENTIFIER AES_KEY_WRAP_OID = new OBJECT_IDENTIFIER("2.16.840.1.101.3.4.1.5");
public static final OBJECT_IDENTIFIER AES_CBC_PAD_OID = new OBJECT_IDENTIFIER("2.16.840.1.101.3.4.1.2");
public static final OBJECT_IDENTIFIER DES3_CBC_PAD_OID = new OBJECT_IDENTIFIER("1.2.840.113549.3.7");
public static final OBJECT_IDENTIFIER DES_CBC_PAD_OID = new OBJECT_IDENTIFIER("1.3.14.3.2.7");
public static KeyWrapAlgorithm fromOID(String wrapOID) throws NoSuchAlgorithmException {
OBJECT_IDENTIFIER oid = new OBJECT_IDENTIFIER(wrapOID);
return fromOID(oid);
}
public static KeyWrapAlgorithm fromOID(OBJECT_IDENTIFIER oid) throws NoSuchAlgorithmException {
if (oid.equals(AES_KEY_WRAP_PAD_OID))
return AES_KEY_WRAP_PAD;
if (oid.equals(AES_KEY_WRAP_OID))
return AES_KEY_WRAP;
if (oid.equals(AES_CBC_PAD_OID))
return AES_CBC_PAD;
if (oid.equals(DES3_CBC_PAD_OID))
return DES3_CBC_PAD;
if (oid.equals(DES_CBC_PAD_OID))
return DES_CBC_PAD;
throw new NoSuchAlgorithmException("Unknown Algorithm for OID: " + oid);
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/KeyWrapper.java 0000664 0000000 0000000 00000012157 14565430767 0025226 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.crypto;
import java.security.spec.AlgorithmParameterSpec;
import java.security.InvalidAlgorithmParameterException;
import java.security.PublicKey;
import java.security.InvalidKeyException;
public interface KeyWrapper {
public void initWrap(SymmetricKey wrappingKey,
AlgorithmParameterSpec parameters)
throws InvalidKeyException, InvalidAlgorithmParameterException;
public void initWrap(PublicKey wrappingKey,
AlgorithmParameterSpec parameters)
throws InvalidKeyException, InvalidAlgorithmParameterException;
/**
* For wrapping keys in plaintext.
*/
public void initWrap()
throws InvalidKeyException, InvalidAlgorithmParameterException;
public void initUnwrap(SymmetricKey unwrappingKey,
AlgorithmParameterSpec parameters)
throws InvalidKeyException, InvalidAlgorithmParameterException;
public void initUnwrap(PrivateKey unwrappingKey,
AlgorithmParameterSpec parameters)
throws InvalidKeyException, InvalidAlgorithmParameterException;
/**
* For plaintext-wrapped keys.
*/
public void initUnwrap()
throws InvalidKeyException, InvalidAlgorithmParameterException;
public byte[] wrap(PrivateKey toBeWrapped)
throws InvalidKeyException, IllegalStateException, TokenException;
public byte[] wrap(SymmetricKey toBeWrapped)
throws InvalidKeyException, IllegalStateException, TokenException;
/**
* Unwraps a private key, creating a permanent private key object.
* A permanent private key object resides on a token until it is
* explicitly deleted from the token.
*
* @param publicKey Used to calculate the key identifier that must be stored
* with the private key. Must be a RSAPublicKey
or a
* DSAPublicKey
.
* @exception InvalidKeyException If the type of the public key does not
* match the type of the private key to be unwrapped.
*/
public PrivateKey unwrapPrivate(byte[] wrapped, PrivateKey.Type type,
PublicKey publicKey)
throws TokenException, InvalidKeyException, IllegalStateException;
/**
* Unwraps a private key, creating a temporary private key object.
* A temporary
* private key is one that does not permanently reside on a token.
* As soon as it is garbage-collected, it is gone forever.
*
* @param publicKey Used to calculate the key identifier that must be stored
* with the private key. Must be a RSAPublicKey
or a
* DSAPublicKey
.
* @exception InvalidKeyException If the type of the public key does not
* match the type of the private key to be unwrapped.
*/
public PrivateKey unwrapTemporaryPrivate(byte[] wrapped,
PrivateKey.Type type, PublicKey publicKey)
throws TokenException, InvalidKeyException, IllegalStateException;
/**
* @param keyLength The expected length of the key in bytes. This is
* only used for variable-length keys (RC4) and non-padding
* algorithms. Otherwise, it can be set to anything(like 0).
* @param usage The operation the key will be used for after it is
* unwrapped. You have to specify this so that the key can be properly
* marked with the operation it supports. Some PKCS #11 tokens require
* that a key be marked for an operation before it can perform that
* operation.
*/
public SymmetricKey unwrapSymmetric(byte[] wrapped, SymmetricKey.Type type,
SymmetricKey.Usage usage, int keyLength)
throws TokenException, IllegalStateException,
InvalidAlgorithmParameterException;
/**
* Unwraps a key and allows it to be used for all operations.
* @param keyLength The expected length of the key in bytes. This is
* only used for variable-length keys (RC4) and non-padding
* algorithms. Otherwise, it can be set to anything(like 0).
*/
public SymmetricKey unwrapSymmetric(byte[] wrapped, SymmetricKey.Type type,
int keyLength)
throws TokenException, IllegalStateException,
InvalidAlgorithmParameterException;
public SymmetricKey unwrapSymmetricPerm(byte[] wrapped, SymmetricKey.Type type,
SymmetricKey.Usage usage, int keyLength)
throws TokenException, IllegalStateException,
InvalidAlgorithmParameterException;
/**
* Unwraps a key and allows it to be used for all operations.
* @param keyLength The expected length of the key in bytes. This is
* only used for variable-length keys (RC4) and non-padding
* algorithms. Otherwise, it can be set to anything(like 0).
*/
public SymmetricKey unwrapSymmetricPerm(byte[] wrapped, SymmetricKey.Type type,
int keyLength)
throws TokenException, IllegalStateException,
InvalidAlgorithmParameterException;
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/NoSuchItemOnTokenException.java 0000664 0000000 0000000 00000001565 14565430767 0030331 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.crypto;
/**
* Thrown if a cryptographic item does not exist on the token it is
* trying to be used on.
*/
public class NoSuchItemOnTokenException extends Exception {
private static final long serialVersionUID = 1L;
public NoSuchItemOnTokenException() {}
public NoSuchItemOnTokenException(String mesg) {
super(mesg);
}
public NoSuchItemOnTokenException(String mesg, Throwable cause) {
super(mesg, cause);
}
public NoSuchItemOnTokenException(String mesg, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(mesg, cause, enableSuppression, writableStackTrace);
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/NoSuchPaddingException.java 0000664 0000000 0000000 00000000702 14565430767 0027473 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.crypto;
/**
* This class is a stub for javax.crypto.NoSuchPaddingException until we
* move to JDK 1.2.
*/
public class NoSuchPaddingException extends Exception {
private static final long serialVersionUID = 1L;
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/ObjectNotFoundException.java 0000664 0000000 0000000 00000001471 14565430767 0027674 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.crypto;
/**
* This exception is thrown whenever something isn't implemented.
*/
public class ObjectNotFoundException extends Exception {
private static final long serialVersionUID = 1L;
public ObjectNotFoundException() { super(); }
public ObjectNotFoundException(String mesg) { super(mesg); }
public ObjectNotFoundException(String mesg, Throwable cause) { super(mesg, cause); }
public ObjectNotFoundException(String mesg, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(mesg, cause, enableSuppression, writableStackTrace);
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/PBEAlgorithm.java 0000664 0000000 0000000 00000013146 14565430767 0025411 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.crypto;
import org.mozilla.jss.asn1.OBJECT_IDENTIFIER;
/**
* Algorithms that can be used for generating symmetric keys from passwords.
*/
public class PBEAlgorithm extends KeyGenAlgorithm {
private EncryptionAlgorithm encAlg;
private int saltLength;
protected PBEAlgorithm(int oidTag, String name, int validStrength,
OBJECT_IDENTIFIER oid, EncryptionAlgorithm encAlg, int saltLength)
{
super(oidTag, name, new FixedKeyStrengthValidator(validStrength),
oid, PBEKeyGenParams.class);
this.encAlg = encAlg;
this.saltLength = saltLength;
}
/**
* Returns the EncryptionAlgorithm that should be used with keys
* generated with this PBEAlgorithm. For example,
* PBE_MD2_DES_CBC.getEncryptionAlg()
returns
* EncryptionAlgorithm.DES_CBC
.
*/
public EncryptionAlgorithm getEncryptionAlg() {
return encAlg;
}
/**
* Returns the number of bytes of salt that should be supplied when
* generating keys with this algorithm.
*
* PKCS #5 algorithms require exactly 8 bytes of salt. PKCS #12
* algorithms take
* a variable length, but recommend that the salt length be at least
* as long as the output of the hash function. For SHA-1, the output
* length is 20 bytes.
*/
public int getSaltLength() {
return saltLength;
}
///////////////////////////////////////////////////////////////////////
// OIDs
///////////////////////////////////////////////////////////////////////
private static final OBJECT_IDENTIFIER PKCS5 = OBJECT_IDENTIFIER.PKCS5;
private static final OBJECT_IDENTIFIER PKCS12_PBE =
OBJECT_IDENTIFIER.PKCS12.subBranch(1);
///////////////////////////////////////////////////////////////////////
// OID mapping
///////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////
// PKCS 5 v2
public static final PBEAlgorithm
PBE_PKCS5_PBKDF2 = new PBEAlgorithm(
SEC_OID_PKCS5_PBKDF2, "PBKDF2", 128,
PKCS5.subBranch(12), EncryptionAlgorithm.AES_128_CBC, 8 );
//////////////////////////////////////////////////////////////
// PKCS 5 v2
public static final PBEAlgorithm
PBE_PKCS5_PBES2 = new PBEAlgorithm(
SEC_OID_PKCS5_PBES2, "PBES2", 128,
PKCS5.subBranch(13), EncryptionAlgorithm.AES_128_CBC, 8 );
//////////////////////////////////////////////////////////////
// PKCS 5 v2
public static final PBEAlgorithm
PBE_PKCS5_PBMAC1 = new PBEAlgorithm(
SEC_OID_PKCS5_PBMAC1, "PBMAC1", 128,
PKCS5.subBranch(14), EncryptionAlgorithm.AES_128_CBC, 8 );
//////////////////////////////////////////////////////////////
public static final PBEAlgorithm
PBE_MD2_DES_CBC = new PBEAlgorithm(
SEC_OID_PKCS5_PBE_WITH_MD2_AND_DES_CBC, "PBE/MD2/DES/CBC", 56,
PKCS5.subBranch(1), EncryptionAlgorithm.DES_CBC, 8 );
//////////////////////////////////////////////////////////////
public static final PBEAlgorithm
PBE_MD5_DES_CBC = new PBEAlgorithm(
SEC_OID_PKCS5_PBE_WITH_MD5_AND_DES_CBC, "PBE/MD5/DES/CBC", 56,
PKCS5.subBranch(3), EncryptionAlgorithm.DES_CBC, 8 );
//////////////////////////////////////////////////////////////
@Deprecated(since="5.0.1", forRemoval=true)
public static final PBEAlgorithm
PBE_SHA1_DES_CBC = new PBEAlgorithm(
SEC_OID_PKCS5_PBE_WITH_SHA1_AND_DES_CBC, "PBE/SHA1/DES/CBC", 56,
PKCS5.subBranch(10), EncryptionAlgorithm.DES_CBC, 8 );
//////////////////////////////////////////////////////////////
@Deprecated(since="5.0.1", forRemoval=true)
public static final PBEAlgorithm
PBE_SHA1_RC4_128 = new PBEAlgorithm(
SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC4,
"PBE/SHA1/RC4-128", 128, PKCS12_PBE.subBranch(1),
EncryptionAlgorithm.RC4, 20 );
//////////////////////////////////////////////////////////////
@Deprecated(since="5.0.1", forRemoval=true)
public static final PBEAlgorithm
PBE_SHA1_RC4_40 = new PBEAlgorithm(
SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC4,
"PBE/SHA1/RC4-40", 40, PKCS12_PBE.subBranch(2),
EncryptionAlgorithm.RC4, 20 );
//////////////////////////////////////////////////////////////
@Deprecated(since="5.0.1", forRemoval=true)
public static final PBEAlgorithm
PBE_SHA1_DES3_CBC = new PBEAlgorithm(
SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_3KEY_TRIPLE_DES_CBC,
"PBE/SHA1/DES3/CBC", 168, PKCS12_PBE.subBranch(3),
EncryptionAlgorithm.DES3_CBC, 20 );
//////////////////////////////////////////////////////////////
@Deprecated(since="5.0.1", forRemoval=true)
public static final PBEAlgorithm
PBE_SHA1_RC2_128_CBC = new PBEAlgorithm(
SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_128_BIT_RC2_CBC,
"PBE/SHA1/RC2-128", 128, PKCS12_PBE.subBranch(5),
EncryptionAlgorithm.RC2_CBC, 20 );
//////////////////////////////////////////////////////////////
@Deprecated(since="5.0.1", forRemoval=true)
public static final PBEAlgorithm
PBE_SHA1_RC2_40_CBC = new PBEAlgorithm(
SEC_OID_PKCS12_V2_PBE_WITH_SHA1_AND_40_BIT_RC2_CBC,
"PBE/SHA1/RC2-40", 40, PKCS12_PBE.subBranch(6),
EncryptionAlgorithm.RC2_CBC, 20 );
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/PBEKeyGenParams.java 0000664 0000000 0000000 00000013312 14565430767 0026004 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.crypto;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.KeySpec;
import org.mozilla.jss.util.Password;
public class PBEKeyGenParams implements AlgorithmParameterSpec, KeySpec {
private Password pass;
private byte[] salt;
private int iterations;
private EncryptionAlgorithm encryptionAlgorithm = EncryptionAlgorithm.DES3_CBC;
private HMACAlgorithm hashAlgorithm = null;
static private final int DEFAULT_SALT_LENGTH = 8;
static private final int DEFAULT_ITERATIONS = 1;
/**
* Creates PBE parameters.
*
* @param pass The password. It will be cloned, so the
* caller is still responsible for clearing it. It must not be null.
* @param salt The salt for the PBE algorithm. Will not be cloned.
* Must not be null. It is the responsibility of the caller to
* use the right salt length for the algorithm. Most algorithms
* use 8 bytes of salt.
* @param iterations The iteration count for the PBE algorithm.
*/
public PBEKeyGenParams(Password pass, byte[] salt, int iterations) {
if (pass == null || salt == null) {
throw new NullPointerException();
}
this.pass = (Password) pass.clone();
this.salt = salt;
this.iterations = iterations;
}
/**
* Creates PBE parameters using default encryption algorithm
* (DES3_EDE3_CBC).
*
* @param pass The password. It will be cloned, so the
* caller is still responsible for clearing it. It must not be null.
* @param salt The salt for the PBE algorithm. Will not be cloned.
* Must not be null. It is the responsibility of the caller to
* use the right salt length for the algorithm. Most algorithms
* use 8 bytes of salt.
* @param iterations The iteration count for the PBE algorithm.
*/
public PBEKeyGenParams(char[] pass, byte[] salt, int iterations) {
this(pass, salt, iterations, null, null);
}
/**
* Creates PBE parameters using default encryption algorithm
* (DES3_EDE3_CBC).
*
* @param pass The password. It will be cloned, so the
* caller is still responsible for clearing it. It must not be null.
* @param salt The salt for the PBE algorithm. Will not be cloned.
* Must not be null. It is the responsibility of the caller to
* use the right salt length for the algorithm. Most algorithms
* use 8 bytes of salt.
* @param iterations The iteration count for the PBE algorithm.
* @param encAlg The encryption algorithm. This is used with SOME
* PBE algorithms for determining the KDF output length.
*/
public PBEKeyGenParams(
char[] pass, byte[] salt, int iterations,
EncryptionAlgorithm encAlg) {
this(pass, salt, iterations, encAlg, null);
}
/**
* Creates PBE parameters using default encryption algorithm
* (DES3_EDE3_CBC).
*
* @param pass The password. It will be cloned, so the
* caller is still responsible for clearing it. It must not be null.
* @param salt The salt for the PBE algorithm. Will not be cloned.
* Must not be null. It is the responsibility of the caller to
* use the right salt length for the algorithm. Most algorithms
* use 8 bytes of salt.
* @param iterations The iteration count for the PBE algorithm.
* @param encAlg The encryption algorithm. This is used with SOME
* PBE algorithms for determining the KDF output length.
* @param hashAlg The hash algorithm. This is used with PBEv2 algorithms
* because it cannot be derived from the key generation algorithm.
*/
public PBEKeyGenParams(
char[] pass, byte[] salt, int iterations,
EncryptionAlgorithm encAlg, HMACAlgorithm hashAlg) {
if (pass == null || salt == null) {
throw new NullPointerException();
}
this.pass = new Password(pass.clone());
this.salt = salt;
this.iterations = iterations;
if (encAlg != null)
this.encryptionAlgorithm = encAlg;
this.hashAlgorithm = hashAlg;
}
/**
* Returns a reference to the password, not a copy.
*/
public Password getPassword() {
return pass;
}
/**
* Returns a reference to the salt.
*/
public byte[] getSalt() {
return salt;
}
/**
* Returns the iteration count.
*/
public int getIterations() {
return iterations;
}
/**
* The encryption algorithm is used with SOME PBE algorithms for
* determining the KDF output length.
*/
public EncryptionAlgorithm getEncryptionAlgorithm() {
return encryptionAlgorithm;
}
/**
* The hash algorithm is used with PBEv2 algorithms because it cannot be
* derived from the key generation algorithm.
*/
public HMACAlgorithm getHashAlgorithm() {
return hashAlgorithm;
}
/**
* Clears the password. This should be called when this object is no
* longer needed so the password is not left around in memory.
*/
public void clear() {
pass.clear();
}
/**
* @deprecated finalize() in Object has been deprecated
*/
@Override
@Deprecated
protected void finalize() throws Throwable {
pass.clear();
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/PKCS11Algorithm.java 0000664 0000000 0000000 00000010547 14565430767 0025707 0 ustar 00root root 0000000 0000000 package org.mozilla.jss.crypto;
import org.mozilla.jss.pkcs11.PKCS11Constants;
public enum PKCS11Algorithm {
CKM_AES_CBC (Algorithm.CKM_AES_CBC, PKCS11Constants.CKM_AES_CBC),
CKM_AES_CBC_PAD (Algorithm.CKM_AES_CBC_PAD, PKCS11Constants.CKM_AES_CBC_PAD),
CKM_AES_ECB (Algorithm.CKM_AES_ECB, PKCS11Constants.CKM_AES_ECB),
CKM_AES_KEY_GEN (Algorithm.CKM_AES_KEY_GEN, PKCS11Constants.CKM_AES_KEY_GEN),
CKM_DES3_CBC_PAD (Algorithm.CKM_DES3_CBC_PAD, PKCS11Constants.CKM_DES3_CBC_PAD),
CKM_DES3_ECB (Algorithm.CKM_DES3_ECB, PKCS11Constants.CKM_DES3_ECB),
CKM_DES3_KEY_GEN (Algorithm.CKM_DES3_KEY_GEN, PKCS11Constants.CKM_DES3_KEY_GEN),
CKM_DES_CBC_PAD (Algorithm.CKM_DES_CBC_PAD, PKCS11Constants.CKM_DES_CBC_PAD),
CKM_DES_KEY_GEN (Algorithm.CKM_DES_KEY_GEN, PKCS11Constants.CKM_DES_KEY_GEN),
CKM_DSA_KEY_PAIR_GEN (Algorithm.CKM_DSA_KEY_PAIR_GEN, PKCS11Constants.CKM_DSA_KEY_PAIR_GEN),
CKM_EC_KEY_PAIR_GEN (Algorithm.CKM_EC_KEY_PAIR_GEN, PKCS11Constants.CKM_EC_KEY_PAIR_GEN),
CKM_NSS_AES_KEY_WRAP (Algorithm.CKM_NSS_AES_KEY_WRAP, PKCS11Constants.CKM_NSS_AES_KEY_WRAP),
CKM_NSS_AES_KEY_WRAP_PAD (Algorithm.CKM_NSS_AES_KEY_WRAP_PAD, PKCS11Constants.CKM_NSS_AES_KEY_WRAP_PAD),
@Deprecated(since="5.0.1", forRemoval=true)
CKM_PBA_SHA1_WITH_SHA1_HMAC (Algorithm.CKM_PBA_SHA1_WITH_SHA1_HMAC, PKCS11Constants.CKM_PBA_SHA1_WITH_SHA1_HMAC),
CKM_RC2_CBC_PAD (Algorithm.CKM_RC2_CBC_PAD, PKCS11Constants.CKM_RC2_CBC_PAD),
CKM_RC2_KEY_GEN (Algorithm.CKM_RC2_KEY_GEN, PKCS11Constants.CKM_RC2_KEY_GEN),
CKM_RC4_KEY_GEN (Algorithm.CKM_RC4_KEY_GEN, PKCS11Constants.CKM_RC4_KEY_GEN),
CKM_RSA_PKCS_KEY_PAIR_GEN (Algorithm.CKM_RSA_PKCS_KEY_PAIR_GEN, PKCS11Constants.CKM_RSA_PKCS_KEY_PAIR_GEN),
@Deprecated(since="5.0.1", forRemoval=true)
CKM_SHA_1_HMAC (Algorithm.CKM_SHA_1_HMAC, PKCS11Constants.CKM_SHA_1_HMAC),
CKM_SHA_256_HMAC (Algorithm.CKM_SHA256_HMAC, PKCS11Constants.CKM_SHA256_HMAC),
CKM_SHA_384_HMAC (Algorithm.CKM_SHA384_HMAC, PKCS11Constants.CKM_SHA384_HMAC),
CKM_SHA_512_HMAC (Algorithm.CKM_SHA512_HMAC, PKCS11Constants.CKM_SHA512_HMAC),
CKM_AES_CMAC (Algorithm.CKM_AES_CMAC, PKCS11Constants.CKM_AES_CMAC),
CKM_SP800_108_COUNTER_KDF (Algorithm.CKM_SP800_108_COUNTER_KDF, PKCS11Constants.CKM_SP800_108_COUNTER_KDF),
CKM_SP800_108_FEEDBACK_KDF (Algorithm.CKM_SP800_108_FEEDBACK_KDF, PKCS11Constants.CKM_SP800_108_FEEDBACK_KDF),
CKM_SP800_108_DOUBLE_PIPELINE_KDF (Algorithm.CKM_SP800_108_DOUBLE_PIPELINE_KDF, PKCS11Constants.CKM_SP800_108_DOUBLE_PIPELINE_KDF),
CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA (Algorithm.CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA, PKCS11Constants.CKM_NSS_SP800_108_COUNTER_KDF_DERIVE_DATA),
CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA (Algorithm.CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA, PKCS11Constants.CKM_NSS_SP800_108_FEEDBACK_KDF_DERIVE_DATA),
CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA (Algorithm.CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA, PKCS11Constants.CKM_NSS_SP800_108_DOUBLE_PIPELINE_KDF_DERIVE_DATA),
CKM_MD2(Algorithm.SEC_OID_MD2, PKCS11Constants.CKM_MD2),
CKM_MD5(Algorithm.SEC_OID_MD5, PKCS11Constants.CKM_MD5),
CKM_SHA_1(Algorithm.SEC_OID_SHA1, PKCS11Constants.CKM_SHA_1),
CKM_SHA256(Algorithm.SEC_OID_SHA256, PKCS11Constants.CKM_SHA256),
CKM_SHA384(Algorithm.SEC_OID_SHA384, PKCS11Constants.CKM_SHA384),
CKM_SHA512(Algorithm.SEC_OID_SHA512, PKCS11Constants.CKM_SHA512);
// Value from Algorithm's constant -- this is an index into Algorithm's
// table.
private int alg_index;
// Value from PKCS11Constants -- this is a constant defined in PKCS #11.
private long pk11_value;
private PKCS11Algorithm(int alg_index, long pk11_value) {
this.alg_index = alg_index;
this.pk11_value = pk11_value;
}
public int getIndex() {
return alg_index;
}
public long getValue() {
return pk11_value;
}
public static PKCS11Algorithm valueOfIndex(int index) {
for (PKCS11Algorithm alg : PKCS11Algorithm.values()) {
if (alg.alg_index == index) {
return alg;
}
}
return null;
}
public static PKCS11Algorithm valueOfConstant(long constant) {
for (PKCS11Algorithm alg : PKCS11Algorithm.values()) {
if (alg.pk11_value == constant) {
return alg;
}
}
return null;
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/PQGParamGenException.java 0000664 0000000 0000000 00000001326 14565430767 0027052 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.crypto;
public class PQGParamGenException extends Exception {
private static final long serialVersionUID = 1L;
public PQGParamGenException() {}
public PQGParamGenException(String mesg) { super(mesg); }
public PQGParamGenException(String mesg, Throwable cause) { super(mesg, cause); }
public PQGParamGenException(String mesg, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(mesg, cause, enableSuppression, writableStackTrace);
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/PQGParams.java 0000664 0000000 0000000 00000017662 14565430767 0024736 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.crypto;
import java.math.BigInteger;
import java.security.spec.DSAParameterSpec;
/**
* PQG parameters for DSA key generation, along with the seed, counter,
* and H values for verification.
*
This class has two main purposes:
* generating PQG parameters and verifying PQG parameters. To generate
* PQG parameters, call one of the static generate
methods.
* They will return a new set of PQG parameters. To verify existing PQG
* parameters, create a new PQGParams
object with the
* constructor and call paramsAreValid
on the object.
*
*
It is necessary to call CryptoManager.initialize
before
* using this class.
*
*/
public class PQGParams extends DSAParameterSpec {
/**
* Creates a PQGParams object from a set of pre-computed DSA
* parameters.
*
* @param P The DSA prime parameter.
* @param Q The DSA sub-prime parameter.
* @param G The DSA base parameter.
* @param seed The Seed used to calculate P, Q, and G.
* @param counter The Counter (C) used to calculate P, Q, and G.
* @param H The H value used to generate P, Q, and G.
*/
public PQGParams(BigInteger P, BigInteger Q, BigInteger G,
BigInteger seed, int counter, BigInteger H)
{
super(P, Q, G);
this.seed = seed;
this.counter = counter;
this.H = H;
}
/**
* Generates P, Q, and G parameters for DSA key generation. Also
* provides the seed, counter, and H values for verification of the
* P, Q, and G. The parameters are generated and then verified
* before being returned. The length of the Seed will equal the
* length of P.
*
* It is necessary to call one of the
* CryptoManager.initialize
functions before calling
* this method.
*
* @param keySize The size of P in bits. Keys generated by these P,
* Q, and G values will have this length. Valid key sizes
* are multiples of 64 in the closed interval [512,1024].
* This also dictates the length of H and Seed.
* @return A new set of P, Q, and G parameters, along with the Seed,
* Counter, and H values used to generate them.
* @exception java.security.InvalidParameterException If the keySize
* is outside the bounds described by the DSA key pair
* generation algorithm.
* @exception org.mozilla.jss.crypto.PQGParamGenException If an error
* occurs during the generation process.
* @see org.mozilla.jss.CryptoManager#initialize
*/
public static PQGParams
generate(int keySize)
throws java.security.InvalidParameterException,
PQGParamGenException
{
PQGParams pqg = generateNative(keySize);
if( ! pqg.paramsAreValid() ) {
throw new PQGParamGenException(
"Generated parameters did not verify correctly");
}
return pqg;
}
/**
* Does the actual work of generation, but does not verify.
*/
private static native PQGParams
generateNative(int keySize)
throws java.security.InvalidParameterException,
PQGParamGenException;
/**
* Generates P, Q, and G parameters for DSA key generation. Also
* provides the seed, counter, and H values for verification of the
* P, Q, and G. The parameters are generated and then verified
* before being returned.
*
* It is necessary to call one of the
* CryptoManager.initialize
functions before calling
* this method.
*
* @param keySize The size of P in bits. Keys generated by these P,
* Q, and G values will have this length. Valid key sizes
* are multiples of 64 in the closed interval [512,1024].
* This also dictates the length of H.
* @param seedBytes The number of bytes in the Seed value used to
* generate P, Q, and G. seedBytes
must be
* from the closed interval [20,255].
* @return A new set of P, Q, and G parameters, along with the Seed,
* Counter, and H values used to generate them.
* @exception java.security.InvalidParameterException If the keySize
* or number of seed bytes is outside the bounds described by the
* DSA key pair generation algorithm.
* @exception org.mozilla.jss.crypto.PQGParamGenException If an error
* occurs during the generation process.
* @see org.mozilla.jss.CryptoManager#initialize
*/
public static PQGParams
generate(int keySize, int seedBytes)
throws java.security.InvalidParameterException,
PQGParamGenException
{
PQGParams pqg = generateNative(keySize, seedBytes);
if( ! pqg.paramsAreValid() ) {
throw new PQGParamGenException(
"Generated parameters did not verify correctly");
}
return pqg;
}
/**
* Does the actual work of generation, but does not verify.
*/
private static native PQGParams
generateNative(int keySize, int seedBytes)
throws java.security.InvalidParameterException,
PQGParamGenException;
/**
* Produces an unsigned byte-array representation of a BigInteger.
*
*
BigInteger adds an extra sign bit to the beginning of its byte
* array representation. In some cases this will cause the size
* of the byte array to increase, which may be unacceptable for some
* applications. This function returns a minimal byte array representing
* the BigInteger without extra sign bits.
*
* @return An unsigned, big-endian byte array representation
* of a BigInteger.
*/
public static byte[] BigIntegerToUnsignedByteArray(BigInteger big) {
byte[] ret;
// big must not be negative
assert(big.signum() != -1);
// bitLength is the size of the data without the sign bit. If
// it exactly fills an integral number of bytes, that means a whole
// new byte will have to be added to accomodate the sign bit. In
// this case we need to remove the first byte.
if(big.bitLength() % 8 == 0) {
byte[] array = big.toByteArray();
// The first byte should just be sign bits
assert( array[0] == 0 );
ret = new byte[array.length-1];
System.arraycopy(array, 1, ret, 0, ret.length);
} else {
ret = big.toByteArray();
}
return ret;
}
/**
* Verifies the PQG parameters using the seed, counter, and H values.
* @return true if the parameters verified correctly, false if they
* did not verify.
*/
public boolean paramsAreValid() {
return paramsAreValidNative(BigIntegerToUnsignedByteArray( getP() ),
BigIntegerToUnsignedByteArray( getQ() ),
BigIntegerToUnsignedByteArray( getG() ),
BigIntegerToUnsignedByteArray( seed ),
counter,
BigIntegerToUnsignedByteArray( H ));
}
private native boolean paramsAreValidNative(byte[] P, byte[] Q, byte[]G,
byte[] seed, int counter, byte[] H);
/**
* @return The Seed used to generate P, Q, and G.
*/
public BigInteger getSeed() {
return seed;
}
/**
* @return The Counter (C) used to generate P, Q, and G.
*/
public int getCounter() {
return counter;
}
/**
* @return The H value used to generate P, Q, and G.
*/
public BigInteger getH() {
return H;
}
private BigInteger seed;
private int counter;
private BigInteger H;
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/Policy.java 0000664 0000000 0000000 00000004510 14565430767 0024366 0 ustar 00root root 0000000 0000000 package org.mozilla.jss.crypto;
import java.math.BigInteger;
import org.mozilla.jss.ssl.SSLProtocolVariant;
import org.mozilla.jss.ssl.SSLSocket;
import org.mozilla.jss.ssl.SSLVersion;
import org.mozilla.jss.ssl.SSLVersionRange;
/**
* This class helps JSS callers align with local system cryptographic policy.
*
* In the event of a policy violation, applications can override policy by
* writing to the desired variable.
*
* Refer to SSLCipher.isSupported() for whether or not a given TLS cipher
* suite is allowed by local policy.
*/
public class Policy {
/**
* Whether or not this JSS instance is enforcing local crypto-policy,
* with respect to key sizes.
*
* Defaults to false; this lets applications use whatever key sizes are
* supported by NSS, at the risk of performing non-compliant operations.
* Set to true to enable enforcement, where it exists.
*/
public static boolean ENFORCING_KEY_SIZES = false;
/**
* Minimum RSA key length in bits permitted by local policy.
*/
public static int RSA_MINIMUM_KEY_SIZE = getRSAMinimumKeySize();
/**
* Minimum RSA public exponent allowed by JSS.
*/
public static BigInteger RSA_MINIMUM_PUBLIC_EXPONENT = BigInteger.valueOf(65537);
/**
* Minimum DH key length in bits permitted by local policy.
*/
public static int DH_MINIMUM_KEY_SIZE = getDHMinimumKeySize();
/**
* Minimum DSA key length in bits permitted by local policy.
*/
public static int DSA_MINIMUM_KEY_SIZE = getDSAMinimumKeySize();
public static SSLVersionRange TLS_VERSION_RANGE = getTLSVersionRange();
public static SSLVersion TLS_MINIMUM_VERSION = TLS_VERSION_RANGE.getMinVersion();
public static SSLVersion TLS_MAXIMUM_VERSION = TLS_VERSION_RANGE.getMaxVersion();
private static SSLVersionRange getTLSVersionRange() {
SSLVersionRange range = new SSLVersionRange(SSLVersion.minSupported(),
SSLVersion.maxSupported());
try {
return SSLSocket.boundSSLVersionRange(SSLProtocolVariant.STREAM, range);
} catch (Exception e) {
return range;
}
}
private static native int getRSAMinimumKeySize();
private static native int getDHMinimumKeySize();
private static native int getDSAMinimumKeySize();
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/PrivateKey.java 0000664 0000000 0000000 00000007053 14565430767 0025217 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.crypto;
import java.security.NoSuchAlgorithmException;
import java.util.Hashtable;
import org.mozilla.jss.asn1.OBJECT_IDENTIFIER;
/**
* Private Keys used by JSS. All the private keys handled by JSS are
* of this type, which is a subtype of java.security.PrivateKey.
*/
public interface PrivateKey extends java.security.PrivateKey {
public static final Type RSA = Type.RSA;
public static final Type DSA = Type.DSA;
public static final Type EC = Type.EC;
public static final Type DiffieHellman = Type.DiffieHellman;
/**
* Returns the type (RSA or DSA) of this private key.
*/
public Type getType();
/**
* Returns the unique ID of this key. Unique IDs can be used to match
* certificates to keys.
*
* @see org.mozilla.jss.crypto.TokenCertificate#getUniqueID
*/
public byte[] getUniqueID() throws TokenException;
/**
* Returns the size, in bits, of the modulus of an RSA key.
* Returns -1 for other types of keys.
*/
public int getStrength();
/**
* Returns the CryptoToken that owns this private key. Cryptographic
* operations with this key may only be performed on the token that
* owns the key.
*/
public CryptoToken getOwningToken();
public static final class Type {
private OBJECT_IDENTIFIER oid;
private String name;
private int pkcs11Type;
private Type() {
}
private Type(OBJECT_IDENTIFIER oid, String name, int pkcs11Type) {
this.oid = oid;
this.name = name;
Object old = oidMap.put(oid, this);
this.pkcs11Type = pkcs11Type;
assert (old == null);
}
private static Hashtable oidMap = new Hashtable<>();
public static Type fromOID(OBJECT_IDENTIFIER oid)
throws NoSuchAlgorithmException {
Object obj = oidMap.get(oid);
if (obj == null) {
throw new NoSuchAlgorithmException();
}
return (Type) obj;
}
/**
* Returns a string representation of the algorithm, such as
* "RSA", "DSA", or "EC".
*/
@Override
public String toString() {
return name;
}
public OBJECT_IDENTIFIER toOID() {
return oid;
}
public int getPKCS11Type() {
return pkcs11Type;
}
// OID for DiffieHellman, from RFC 2459 7.3.2.
public static OBJECT_IDENTIFIER DH_OID = new OBJECT_IDENTIFIER(new long[] { 1, 2, 840, 10046, 2, 1 });
// From PKCS #11
private static int CKK_RSA = 0x0;
private static int CKK_DSA = 0x1;
private static int CKK_DH = 0x2;
private static int CKK_EC = 0x3;
private static int CKK_X9_42_DH = 0x4;
private static int CKK_KEA = 0x5;
public static final Type RSA = new Type(
OBJECT_IDENTIFIER.PKCS1.subBranch(1), "RSA", CKK_RSA);
public static final Type DSA = new Type(
Algorithm.ANSI_X9_ALGORITHM.subBranch(1), "DSA", CKK_DSA);
public static final Type EC = new Type(
Algorithm.ANSI_X962_OID.subBranch(2).subBranch(1), "EC", CKK_EC);
public static final Type DiffieHellman = new Type(
DH_OID, "DiffieHellman", CKK_DH);
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/RSAParameterSpec.java 0000664 0000000 0000000 00000002535 14565430767 0026235 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.crypto;
import java.math.BigInteger;
import java.security.spec.RSAKeyGenParameterSpec;
/**
* This class specifies the parameters used for generating an RSA key pair.
* @deprecated This class has been deprecated in favour of the one provided java
* {@link RSAKeyGenParameterSpec}.
*/
@Deprecated(since = "5.4", forRemoval = true)
public class RSAParameterSpec extends RSAKeyGenParameterSpec {
/**
* Creates a new RSAParameterSpec with the specified parameter values.
* @param keySize The size of the modulus in bits.
* @param publicExponent The public exponent e. Common values
* are 3, 17, and 65537. 65537 is recommended.
*/
public RSAParameterSpec(int keySize, BigInteger publicExponent) {
super(keySize, publicExponent);
}
/**
* Returns the size of the modulus in bits.
*
* @deprecated This method has been deprecated in favour of the one provided by the superclass
* {@link RSAKeyGenParameterSpec#getKeysize()}.
*/
@Deprecated(since = "5.4", forRemoval = true)
public int getKeySize() { return getKeysize(); }
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/SecretDecoderRing.java 0000664 0000000 0000000 00000005367 14565430767 0026475 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.crypto;
import java.io.UnsupportedEncodingException;
/**
* This is a special-purpose interface for NSS. It is used for encrypting
* data with a secret key stored in the NSS key database (which is in turn
* protected with a password). It thus provides a quick, convenient way
* to encrypt stuff your application wants to keep around for its own use:
* for example, the list of web passwords stored in the web browser.
*
* A dedicated key is used to encrypt all SecretDecoderRing data.
* The same key is used for all SDR data, and not for any other data.
* This key will be generated the first time it is needed.
*
*
The cipher used is DES3-EDE (Triple-DES) in CBC mode. The ciphertext
* is DER-encoded in the following ASN.1 data structure:
*
* SEQUENCE {
* keyid OCTET STRING,
* alg AlgorithmIdentifier,
* ciphertext OCTET STRING }
*
*
* You must set the password on the Internal Key Storage Token
* (aka software token, key3.db) before you use the SecretDecoderRing.
*/
public class SecretDecoderRing {
public static final String encodingFormat = "UTF-8";
/**
* Encrypts the given plaintext with the Secret Decoder Ring key stored
* in the NSS key database.
*/
public native byte[] encrypt(byte[] plaintext)
throws TokenException;
/**
* Encrypts the given plaintext string with the Secret Decoder Ring key
* stored in the NSS key database.
*/
public byte[] encrypt(String plaintext) throws TokenException {
try {
return encrypt(plaintext.getBytes(encodingFormat));
} catch(UnsupportedEncodingException e) {
// this shouldn't happen, because we use a universally-supported
// charset
throw new RuntimeException(e.getMessage());
}
}
/**
* Decrypts the given ciphertext with the Secret Decoder Ring key stored
* in the NSS key database.
*/
public native byte[] decrypt(byte[] ciphertext)
throws TokenException;
/**
* Decrypts the given ciphertext with the Secret Decoder Ring key stored
* in the NSS key database, returning the original plaintext string.
*/
public String decryptToString(byte[] ciphertext)
throws TokenException {
try {
return new String(decrypt(ciphertext), encodingFormat);
} catch(UnsupportedEncodingException e) {
// this shouldn't happen, because we use a universally-supported
// charset
throw new RuntimeException(e.getMessage());
}
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/SecretKeyFacade.java 0000664 0000000 0000000 00000001327 14565430767 0026114 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.crypto;
public class SecretKeyFacade implements javax.crypto.SecretKey {
private static final long serialVersionUID = 1L;
public SymmetricKey key;
public SecretKeyFacade(SymmetricKey symk) {
key = symk;
}
@Override
public String getAlgorithm() {
return key.getAlgorithm();
}
@Override
public byte[] getEncoded() {
return key.getEncoded();
}
@Override
public String getFormat() {
return key.getFormat();
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/ShortBufferException.java 0000664 0000000 0000000 00000000706 14565430767 0027242 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.crypto;
/**
* This class is a placeholder for javax.crypto.ShortBufferException until
* we move to JDK 1.2.
*/
public class ShortBufferException extends Exception {
private static final long serialVersionUID = 1L; }
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/Signature.java 0000664 0000000 0000000 00000015147 14565430767 0025100 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.crypto;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.Provider;
import java.security.PublicKey;
import java.security.SignatureException;
import java.security.spec.AlgorithmParameterSpec;
/**
* A class for producing and verifying digital signatures.
* Instances of this class can be obtain from CryptoToken
s.
*
* @see org.mozilla.jss.crypto.CryptoToken#getSignatureContext
*/
public class Signature {
protected Signature() {
}
Signature(SignatureAlgorithm algorithm, SignatureSpi engine) {
this.algorithm = algorithm;
this.engine = engine;
}
/**
* This is not supported yet.
*/
public Provider getProvider() {
throw new RuntimeException("Signature.getProvider() is not yet implemented");
}
/**
* Supplying sources of randoms is not supported yet.
* public void initSign(PrivateKey privateKey, SecureRandom random)
* throws InvalidKeyException, TokenException
* {
* engine.engineInitSign(privateKey, random);
* }
*/
/**
* Initialize the signature context for signing.
*
* @param privateKey The private key with which to sign.
* @exception InvalidKeyException If the key is the wrong type for the
* algorithm or does not exist on the token of this signature
* context.
* @exception TokenException If an error occurred on the token.
*/
public void initSign(PrivateKey privateKey)
throws InvalidKeyException, TokenException {
engine.engineInitSign(privateKey);
}
/**
* Initialize the signature context for verifying.
*
* @param publicKey The public key with which to verify the signature.
* @exception InvalidKeyException If the key is the wrong type for the
* algorithm.
* @exception TokenException If an error occurs on the token.
*/
public void initVerify(PublicKey publicKey)
throws InvalidKeyException, TokenException {
engine.engineInitVerify(publicKey);
}
/**
* Set parameters for the signing algorithm. This is currently not
* supported or needed.
*
* @param params Parameters for the signing algorithm.
* @exception InvalidAlgorithmParameterException If there is something wrong
* with the parameters.
* @exception TokenException If an error occurs on the token.
*/
public void setParameter(AlgorithmParameterSpec params)
throws InvalidAlgorithmParameterException, TokenException {
engine.engineSetParameter(params);
}
/**
* Finish a signing operation and return the signature.
*
* @exception SignatureException If an error occurs with the signing
* operation.
* @exception TokenException If an error occurs on the token.
* @return The signature.
*/
public byte[] sign() throws SignatureException, TokenException {
return engine.engineSign();
}
/**
* Finish a signing operation and store the signature in the provided
* buffer.
*
* @param outbuf Buffer to hold the signature
* @param offset Offset in buffer at which to store signature.
* @param len Number of bytes of buffer available for signature.
* @return int The number of bytes placed into outbuf.
* @exception SignatureException If an error occurred while signing, or
* len was insufficient to contain the signature.
* @exception TokenException If an error occurred on the token.
*/
public int sign(byte[] outbuf, int offset, int len)
throws SignatureException, TokenException {
return engine.engineSign(outbuf, offset, len);
}
/**
* Finish a verification operation.
*
* @param signature The signature to be verified.
* @return true if the signature is valid, false if it is invalid.
* @exception SignatureException If an error occurred with the verification
* operation
* @exception TokenException If an error occurred on the token.
*/
public boolean verify(byte[] signature)
throws SignatureException, TokenException {
return engine.engineVerify(signature);
}
/**
* Provide more data for a signature or verification operation.
*
* @param b A byte to be signed or verified.
* @exception SignatureException If an error occurs in the
* signature/verifcation.
* @exception TokenException If an error occurs on the token.
*/
public void update(byte b)
throws SignatureException, TokenException {
engine.engineUpdate(b);
}
/**
* Provide more data for a signature or verification operation.
*
* @param data An array of bytes to be signed or verified.
* @exception SignatureException If an error occurs in the
* signature/verifcation.
* @exception TokenException If an error occurs on the token.
*/
public void update(byte[] data)
throws SignatureException, TokenException {
engine.engineUpdate(data, 0, data.length);
}
/**
* Provide more data for a signature or verification operation.
*
* @param data An array of bytes, some of which will be signed or verified.
* @param off The beginning offset of the bytes to be signed/verified.
* @param len The number of bytes to be signed/verified.
* @exception SignatureException If an error occurs in the
* signature/verification.
* @exception TokenException If an error occurs on the token.
*/
public void update(byte[] data, int off, int len)
throws SignatureException, TokenException {
engine.engineUpdate(data, off, len);
}
/**
* Returns the name of the algorithm to be used for signing.
*/
public String getAlgorithm() {
return algorithm.toString();
}
/**
* Returns the algorithm to be used for signing.
*/
public SignatureAlgorithm getAlgorithmID() {
return algorithm;
}
/**
* Cloning is not supported yet
*/
@Override
protected Object clone() throws CloneNotSupportedException {
// no cloning for now
throw new CloneNotSupportedException();
}
protected SignatureAlgorithm algorithm;
protected SignatureSpi engine;
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/SignatureAlgorithm.java 0000664 0000000 0000000 00000021643 14565430767 0026745 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.crypto;
import java.security.NoSuchAlgorithmException;
import java.util.Hashtable;
import org.mozilla.jss.asn1.OBJECT_IDENTIFIER;
/**
* Algorithms that can be used for signing.
*/
public class SignatureAlgorithm extends Algorithm {
private static Hashtable oidMap = new Hashtable<>();
protected SignatureAlgorithm(int oidIndex, String name,
SignatureAlgorithm signingAlg, DigestAlgorithm digestAlg,
OBJECT_IDENTIFIER oid)
{
super(oidIndex, name, oid);
if(signingAlg == null) {
this.signingAlg = this;
} else {
this.signingAlg = signingAlg;
}
this.digestAlg = digestAlg;
oidMap.put(oid, this);
}
/**
* Looks up the signature algorithm with the given OID.
* @exception NoSuchAlgorithmException If no algorithm is found with this
* OID.
*/
public static SignatureAlgorithm fromOID(OBJECT_IDENTIFIER oid)
throws NoSuchAlgorithmException
{
Object alg = oidMap.get(oid);
if( alg == null ) {
throw new NoSuchAlgorithmException();
}
return (SignatureAlgorithm) alg;
}
/**
* The raw encryption portion of the signature algorithm. For example,
* SignatureAlgorithm.RSASignatureWithMD2Digest.getSigningAlg ==
* SignatureAlgorithm.RSASignature.
*/
public Algorithm getSigningAlg() {
return signingAlg;
}
public SignatureAlgorithm getRawAlg() {
return signingAlg;
}
private SignatureAlgorithm signingAlg;
/**
* The digest portion of the signature algorithm.
*/
private DigestAlgorithm digestAlg;
public DigestAlgorithm getDigestAlg() throws NoSuchAlgorithmException {
if (digestAlg == null) {
throw new NoSuchAlgorithmException();
}
return digestAlg;
}
public DigestAlgorithm setDigestAlg(DigestAlgorithm alg) throws NoSuchAlgorithmException {
if (alg == null) {
throw new NoSuchAlgorithmException();
}
return digestAlg = alg;
}
//////////////////////////////////////////////////////////////////////
// Signature Algorithms
//////////////////////////////////////////////////////////////////////
/**********************************************************************
* Raw RSA signing. This algorithm does not do any hashing, it merely
* encrypts its input, which should be a hash.
*/
public static final SignatureAlgorithm
RSASignature = new SignatureAlgorithm(SEC_OID_PKCS1_RSA_ENCRYPTION, "RSA",
null, null, OBJECT_IDENTIFIER.PKCS1.subBranch(1) );
/**********************************************************************
* Raw DSA signing. This algorithm does not do any hashing, it merely
* operates on its input, which should be a hash.
*/
public static final SignatureAlgorithm
DSASignature = new SignatureAlgorithm(SEC_OID_ANSIX9_DSA_SIGNATURE, "DSA",
null, null, ANSI_X9_ALGORITHM.subBranch(1) );
/**********************************************************************
* Raw EC signing. This algorithm does not do any hashing, it merely
* operates on its input, which should be a hash.
*/
public static final SignatureAlgorithm
ECSignature = new SignatureAlgorithm(SEC_OID_ANSIX962_ECDSA_SIGNATURE_SPECIFIED_DIGEST,
"EC",
null, null, ANSI_X962_OID.subBranch(2).subBranch(1) );
//////////////////////////////////////////////////////////////////////
public static final SignatureAlgorithm
RSASignatureWithMD2Digest =
new SignatureAlgorithm(SEC_OID_PKCS1_MD2_WITH_RSA_ENCRYPTION,
"RSASignatureWithMD2Digest", RSASignature, DigestAlgorithm.MD2,
OBJECT_IDENTIFIER.PKCS1.subBranch(2) );
//////////////////////////////////////////////////////////////////////
public static final SignatureAlgorithm
RSASignatureWithMD5Digest =
new SignatureAlgorithm(SEC_OID_PKCS1_MD5_WITH_RSA_ENCRYPTION,
"RSASignatureWithMD5Digest", RSASignature, DigestAlgorithm.MD5,
OBJECT_IDENTIFIER.PKCS1.subBranch(4) );
//////////////////////////////////////////////////////////////////////
@Deprecated(since="5.0.1", forRemoval=true)
public static final SignatureAlgorithm
RSASignatureWithSHA1Digest =
new SignatureAlgorithm(SEC_OID_PKCS1_SHA1_WITH_RSA_ENCRYPTION,
"RSASignatureWithSHA1Digest", RSASignature, DigestAlgorithm.SHA1,
OBJECT_IDENTIFIER.PKCS1.subBranch(5) );
//////////////////////////////////////////////////////////////////////
@Deprecated(since="5.0.1", forRemoval=true)
public static final SignatureAlgorithm
DSASignatureWithSHA1Digest =
new SignatureAlgorithm(SEC_OID_ANSIX9_DSA_SIGNATURE_WITH_SHA1_DIGEST,
"DSASignatureWithSHA1Digest", DSASignature, DigestAlgorithm.SHA1,
ANSI_X9_ALGORITHM.subBranch(3) );
//////////////////////////////////////////////////////////////////////
@Deprecated(since="5.0.1", forRemoval=true)
public static final SignatureAlgorithm
ECSignatureWithSHA1Digest =
new SignatureAlgorithm(SEC_OID_ANSIX962_ECDSA_SHA1_SIGNATURE,
"ECSignatureWithSHA1Digest", ECSignature, DigestAlgorithm.SHA1,
ANSI_X962_OID.subBranch(4).subBranch(1) );
//////////////////////////////////////////////////////////////////////
public static final SignatureAlgorithm
ECSignatureWithSHA256Digest =
new SignatureAlgorithm(SEC_OID_ANSIX962_ECDSA_SHA256_SIGNATURE,
"ECSignatureWithSHA256Digest", ECSignature, DigestAlgorithm.SHA256,
ANSI_X962_OID.subBranch(4).subBranch(3).subBranch(2) );
//////////////////////////////////////////////////////////////////////
public static final SignatureAlgorithm
ECSignatureWithSHA384Digest =
new SignatureAlgorithm(SEC_OID_ANSIX962_ECDSA_SHA384_SIGNATURE,
"ECSignatureWithSHA384Digest", ECSignature, DigestAlgorithm.SHA384,
ANSI_X962_OID.subBranch(4).subBranch(3).subBranch(3) );
//////////////////////////////////////////////////////////////////////
public static final SignatureAlgorithm
ECSignatureWithSHA512Digest =
new SignatureAlgorithm(SEC_OID_ANSIX962_ECDSA_SHA512_SIGNATURE,
"ECSignatureWithSHA512Digest", ECSignature, DigestAlgorithm.SHA512,
ANSI_X962_OID.subBranch(4).subBranch(3).subBranch(4) );
//////////////////////////////////////////////////////////////////////
public static final SignatureAlgorithm
RSASignatureWithSHA256Digest =
new SignatureAlgorithm(SEC_OID_PKCS1_SHA256_WITH_RSA_ENCRYPTION,
"RSASignatureWithSHA256Digest", RSASignature, DigestAlgorithm.SHA256,
OBJECT_IDENTIFIER.PKCS1.subBranch(11));
//////////////////////////////////////////////////////////////////////
public static final SignatureAlgorithm
RSASignatureWithSHA384Digest =
new SignatureAlgorithm(SEC_OID_PKCS1_SHA384_WITH_RSA_ENCRYPTION,
"RSASignatureWithSHA384Digest", RSASignature, DigestAlgorithm.SHA384,
OBJECT_IDENTIFIER.PKCS1.subBranch(12));
//////////////////////////////////////////////////////////////////////
public static final SignatureAlgorithm
RSASignatureWithSHA512Digest =
new SignatureAlgorithm(SEC_OID_PKCS1_SHA512_WITH_RSA_ENCRYPTION,
"RSASignatureWithSHA512Digest", RSASignature, DigestAlgorithm.SHA512,
OBJECT_IDENTIFIER.PKCS1.subBranch(13));
//////////////////////////////////////////////////////////////////////
/**
* Version with no digest set: must call setDigestAlg() after initialization
* to choose the proper variant.
*/
public static final SignatureAlgorithm
RSAPSSSignature =
new SignatureAlgorithm(SEC_OID_PKCS1_RSA_PSS_SIGNATURE,
"RSAPSSSignature", null, null,
OBJECT_IDENTIFIER.PKCS1.subBranch(10));
public static final SignatureAlgorithm
RSAPSSSignatureWithSHA256Digest =
new SignatureAlgorithm(SEC_OID_PKCS1_RSA_PSS_SIGNATURE,
"RSAPSSSignatureWithSHA256Digest", null, DigestAlgorithm.SHA256,
OBJECT_IDENTIFIER.PKCS1.subBranch(10));
public static final SignatureAlgorithm
RSAPSSSignatureWithSHA384Digest =
new SignatureAlgorithm(SEC_OID_PKCS1_RSA_PSS_SIGNATURE,
"RSAPSSSignatureWithSHA384Digest", null, DigestAlgorithm.SHA384,
OBJECT_IDENTIFIER.PKCS1.subBranch(10));
public static final SignatureAlgorithm
RSAPSSSignatureWithSHA512Digest =
new SignatureAlgorithm(SEC_OID_PKCS1_RSA_PSS_SIGNATURE,
"RSAPSSSignatureWithSHA512Digest", null, DigestAlgorithm.SHA512,
OBJECT_IDENTIFIER.PKCS1.subBranch(10));
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/SignatureSpi.java 0000664 0000000 0000000 00000002650 14565430767 0025547 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.crypto;
import java.security.*;
import java.security.SecureRandom;
import java.security.spec.AlgorithmParameterSpec;
/**
* You don't need to use this unless you are hacking JSS.
*/
public abstract class SignatureSpi {
public abstract void engineInitVerify(PublicKey publicKey)
throws InvalidKeyException, TokenException;
public abstract void engineInitSign(PrivateKey privateKey)
throws InvalidKeyException, TokenException;
public abstract void engineInitSign(PrivateKey privateKey,
SecureRandom random)
throws InvalidKeyException, TokenException;
public abstract void engineUpdate(byte b)
throws SignatureException, TokenException;
public abstract void engineUpdate(byte[] b, int off, int len)
throws SignatureException, TokenException;
public abstract byte[] engineSign()
throws SignatureException, TokenException;
public abstract int engineSign(byte[] outbuf, int offset, int len)
throws SignatureException, TokenException;
public abstract boolean engineVerify(byte[] sigBytes)
throws SignatureException, TokenException;
public abstract void engineSetParameter(AlgorithmParameterSpec params)
throws InvalidAlgorithmParameterException, TokenException;
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/SymmetricKey.java 0000664 0000000 0000000 00000016145 14565430767 0025563 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.crypto;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.Hashtable;
import org.mozilla.jss.pkcs11.KeyType;
import org.mozilla.jss.pkcs11.PKCS11Constants;
public interface SymmetricKey extends javax.crypto.SecretKey {
public static final Type GENERIC_SECRET = Type.GENERIC_SECRET;
public static final Type DES = Type.DES;
public static final Type DES3 = Type.DES3;
public static final Type RC4 = Type.RC4;
public static final Type RC2 = Type.RC2;
@Deprecated(since="5.0.1", forRemoval=true)
public static final Type SHA1_HMAC = Type.SHA1_HMAC;
public static final Type SHA256_HMAC = Type.SHA256_HMAC;
public static final Type SHA384_HMAC = Type.SHA384_HMAC;
public static final Type SHA512_HMAC = Type.SHA512_HMAC;
public static final Type AES = Type.AES;
public Type getType();
public CryptoToken getOwningToken();
public int getStrength();
public int getLength();
public byte[] getKeyData() throws NotExtractableException;
public static class NotExtractableException extends Exception {
private static final long serialVersionUID = 1L;
public NotExtractableException() {
super();
}
public NotExtractableException(String mesg) {
super(mesg);
}
}
@Override
String getAlgorithm();
@Override
byte[] getEncoded();
@Override
String getFormat();
String getNickName();
void setNickName(String nickName);
public final static class Type {
// all names converted to lowercase for case insensitivity
private static Hashtable nameMap = new Hashtable<>();
private static ArrayList allTypes = new ArrayList<>();
private String[] names;
private KeyGenAlgorithm keyGenAlg;
private KeyType keyType;
private Type() {
}
private Type(String[] names, KeyGenAlgorithm keyGenAlg, KeyType keyType) {
this.names = names;
this.keyGenAlg = keyGenAlg;
this.keyType = keyType;
for (String name : names) {
nameMap.put(name.toLowerCase(), this);
}
allTypes.add(this);
}
public static final Type GENERIC_SECRET = new Type(new String[] { "GenericSecret", "GENERIC_SECRET" },
KeyGenAlgorithm.GENERIC_SECRET, KeyType.GENERIC_SECRET);
public static final Type DES = new Type(new String[] { "DES" }, KeyGenAlgorithm.DES, KeyType.DES);
public static final Type DES3 = new Type(new String[] { "DESede", "TDES", "3DES", "DES3" },
KeyGenAlgorithm.DES3, KeyType.DES3);
public static final Type DESede = DES3;
public static final Type RC4 = new Type(new String[] { "RC4" }, KeyGenAlgorithm.RC4, KeyType.RC4);
public static final Type RC2 = new Type(new String[] { "RC2" }, KeyGenAlgorithm.RC2, KeyType.RC4);
@Deprecated(since="5.0.1", forRemoval=true)
public static final Type SHA1_HMAC = new Type(
new String[] { "SHA1_HMAC", "SHA1-HMAC", "SHA1HMAC", "HMAC_SHA1", "HMAC-SHA1", "HMACSHA1" },
KeyGenAlgorithm.SHA1_HMAC, KeyType.SHA1_HMAC);
public static final Type SHA256_HMAC = new Type(
new String[] { "SHA256_HMAC", "SHA256-HMAC", "SHA256HMAC", "HMAC_SHA256", "HMAC-SHA256", "HMACSHA256" },
KeyGenAlgorithm.SHA256_HMAC, KeyType.SHA256_HMAC);
public static final Type SHA384_HMAC = new Type(
new String[] { "SHA384_HMAC", "SHA384-HMAC", "SHA384HMAC", "HMAC_SHA384", "HMAC-SHA384", "HMACSHA384" },
KeyGenAlgorithm.SHA384_HMAC, KeyType.SHA384_HMAC);
public static final Type SHA512_HMAC = new Type(
new String[] { "SHA512_HMAC", "SHA512-HMAC", "SHA512HMAC", "HMAC_SHA512", "HMAC-SHA512", "HMACSHA512" },
KeyGenAlgorithm.SHA512_HMAC, KeyType.SHA512_HMAC);
@Deprecated(since="5.0.1", forRemoval=true)
public static final Type PBA_SHA1_HMAC = new Type(new String[] { "PBA_SHA1_HMAC" },
KeyGenAlgorithm.PBA_SHA1_HMAC, null);
public static final Type AES = new Type(new String[] { "AES" }, KeyGenAlgorithm.AES, KeyType.AES);
@Override
public String toString() {
return names[0];
}
public String[] getAliases() {
return names;
}
public KeyGenAlgorithm getKeyGenAlg() throws NoSuchAlgorithmException {
if (keyGenAlg == null) {
throw new NoSuchAlgorithmException(names[0]);
}
return keyGenAlg;
}
public KeyType getKeyType() {
return keyType;
}
public static Type fromName(String name)
throws NoSuchAlgorithmException {
Object type = nameMap.get(name.toLowerCase());
if (type == null) {
throw new NoSuchAlgorithmException();
} else {
return (Type) type;
}
}
public static Type fromKeyType(KeyType type) {
for (Type current : allTypes) {
if (current.getKeyType() == type) {
return current;
}
}
return null;
}
}
/**
* In PKCS #11, each key can be marked with the operations it will
* be used to perform. Some tokens require that a key be marked for
* an operation before the key can be used to perform that operation;
* other tokens don't care.
*
*
* When you unwrap a symmetric key, you must specify which one of these
* operations it will be used to perform.
*/
public enum Usage {
ENCRYPT(PKCS11Constants.CKF_ENCRYPT, PKCS11Constants.CKA_ENCRYPT), DECRYPT(PKCS11Constants.CKF_DECRYPT,
PKCS11Constants.CKA_DECRYPT), WRAP(PKCS11Constants.CKF_WRAP, PKCS11Constants.CKA_WRAP), UNWRAP(
PKCS11Constants.CKF_UNWRAP,
PKCS11Constants.CKA_UNWRAP), SIGN(PKCS11Constants.CKF_SIGN, PKCS11Constants.CKA_SIGN), VERIFY(
PKCS11Constants.CKF_VERIFY, PKCS11Constants.CKA_VERIFY);
private final long value;
private final long cka_value;
Usage(long value, long cka_value) {
this.value = value;
this.cka_value = cka_value;
}
/**
* @deprecated Use ordinal()
instead.
*/
@Deprecated
public int getVal() {
return ordinal();
}
/**
* Get PKCS #11 CKF_ value.
*/
public long value() {
return value;
}
/**
* Get PKCS #11 CKA_ value.
*
* @deprecated Use value()
to get PKCS #11 CKF_ value instead.
*/
@Deprecated
public long getPKCS11Constant() {
return cka_value;
}
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/SymmetricKeyDeriver.java 0000664 0000000 0000000 00000006074 14565430767 0027104 0 ustar 00root root 0000000 0000000 /* ***** BEGIN LICENSE BLOCK *****
* Version: MPL 1.1/GPL 2.0/LGPL 2.1
*
* The contents of this file are subject to the Mozilla Public License Version
* 1.1 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
* http://www.mozilla.org/MPL/
*
* Software distributed under the License is distributed on an "AS IS" basis,
* WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
* for the specific language governing rights and limitations under the
* License.
*
* The Original Code is the Netscape Security Services for Java.
*
* The Initial Developer of the Original Code is
* Netscape Communications Corporation.
* Portions created by the Initial Developer are Copyright (C) 1998-2000
* the Initial Developer. All Rights Reserved.
*
* Contributor(s):
*
* Alternatively, the contents of this file may be used under the terms of
* either the GNU General Public License Version 2 or later (the "GPL"), or
* the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
* in which case the provisions of the GPL or the LGPL are applicable instead
* of those above. If you wish to allow use of your version of this file only
* under the terms of either the GPL or the LGPL, and not to allow others to
* use your version of this file under the terms of the MPL, indicate your
* decision by deleting the provisions above and replace them with the notice
* and other provisions required by the GPL or the LGPL. If you do not delete
* the provisions above, a recipient may use your version of this file under
* the terms of any one of the MPL, the GPL or the LGPL.
*
* ***** END LICENSE BLOCK ***** */
package org.mozilla.jss.crypto;
import java.security.InvalidKeyException;
public interface SymmetricKeyDeriver {
/* Use with the encrypt type mechanisms
Example: initDerive(
symKey, (PKCS11Constants.CKM_DES3_ECB_ENCRYPT_DATA) 4354L, derivationData, null,
PKCS11Constants.CKM_DES3_ECB, PKCS11Constants.CKA_DERIVE, 16);
*/
public abstract void initDerive(SymmetricKey baseKey,
long deriveMech, byte[] param, byte[] iv, long targetMech, long operation, long keySize)
throws InvalidKeyException;
/* Use with key extraction and key concatanation mechanisms
Example:
param: byte array that has the bit position of where to extract
initDerive(
derivedKey, PKCS11Constants.CKM_EXTRACT_KEY_FROM_KEY,param,null,
PKCS11Constants.CKA_ENCRYPT, PKCS11Constants.CKA_DERIVE,8);
initDerive(
baseSymKey,secondarySymKey, PKCS11Constants.CKM_CONCATENATE_BASE_AND_KEY,null,null,
PKCS11Constants.CKM_DES3_ECB, PKCS11Constants.CKA_DERIVE,0);
*/
public abstract void initDerive(SymmetricKey baseKey,
SymmetricKey secondaryKey, long deriveMech, byte[] param, byte[] iv, long targetMech, long operation, long keySize)
throws InvalidKeyException;
public abstract SymmetricKey derive()
throws TokenException;
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/TokenCertificate.java 0000664 0000000 0000000 00000001757 14565430767 0026364 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.crypto;
/**
* An X509 Certificate that lives on a PKCS #11 token.
* Many of the X509Certificates returned by JSS calls are actually
* TokenCertificates.
* To find out if an X509Certificate is a TokenCertificate, use
* instanceof
.
*/
public interface TokenCertificate extends X509Certificate {
/**
* Returns the unique ID of this key. Unique IDs can be used to match
* certificates to keys.
*
* @see org.mozilla.jss.crypto.PrivateKey#getUniqueID
*/
public abstract byte[] getUniqueID();
/**
* Returns the CryptoToken that owns this certificate. Cryptographic
* operations with this key may only be performed on the token that
* owns the key.
*/
public abstract CryptoToken getOwningToken();
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/TokenException.java 0000664 0000000 0000000 00000001740 14565430767 0026070 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.crypto;
/**
* This class indicates that an unknown error occurred on a CryptoToken.
* The nature of CryptoTokens makes such unpredictable errors possible.
* For example, a smartcard could be yanked out of its slot in the middle
* of a cryptographic operation.
*/
public class TokenException extends Exception {
private static final long serialVersionUID = 1L;
public TokenException() { super(); }
public TokenException(String mesg) {
super(mesg);
}
public TokenException(String mesg, Throwable cause) {
super(mesg, cause);
}
public TokenException(String mesg, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(mesg, cause, enableSuppression, writableStackTrace);
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/TokenRuntimeException.java 0000664 0000000 0000000 00000002012 14565430767 0027425 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.crypto;
/**
* This class indicates that an unknown error occurred on a CryptoToken.
* The nature of CryptoTokens makes such unpredictable errors possible.
* For example, a smartcard could be yanked out of its slot in the middle
* of a cryptographic operation.
*/
public class TokenRuntimeException extends RuntimeException {
private static final long serialVersionUID = 1L;
public TokenRuntimeException() { super(); }
public TokenRuntimeException(String mesg) {
super(mesg);
}
public TokenRuntimeException(String mesg, Throwable cause) {
super(mesg, cause);
}
public TokenRuntimeException(String mesg, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(mesg, cause, enableSuppression, writableStackTrace);
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/TokenSupplier.java 0000664 0000000 0000000 00000001411 14565430767 0025730 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.crypto;
/**
* An interface that allows providers to access CryptoManager without actually
* knowing about CryptoManager. This is necessary to prevent cyclic
* dependencies. CryptoManager knows about the providers, so the providers
* can't know about CryptoManager. Instead, CryptoManager implements
* this interface.
*/
public interface TokenSupplier {
public CryptoToken getInternalCryptoToken();
public JSSSecureRandom getSecureRNG();
public CryptoToken getThreadToken();
public void setThreadToken(CryptoToken token);
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/TokenSupplierManager.java 0000664 0000000 0000000 00000001644 14565430767 0027233 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.crypto;
/**
* The org.mozilla.jss.provider package comes before CryptoManager in
* the dependency list, so this class is used to allow them to access
* CryptoManager sneakily. When CryptoManager initializes, it registers
* itself as a token supplier with setTokenSupplier
. Then
* the providers call getTokenSupplier
when they need to use
* CryptoManager. CryptoManager implements the TokenSupplier interface.
*/
public class TokenSupplierManager {
static private TokenSupplier supplier;
static public void setTokenSupplier(TokenSupplier ts) {
supplier = ts;
}
static public TokenSupplier getTokenSupplier() {
return supplier;
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/Tunnel.java 0000664 0000000 0000000 00000001127 14565430767 0024375 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.crypto;
/**
* This is a private JSS class that allows the pkcs11 package access
* to some of the
* package methods in the crypto package. A friend declaration would
* have been ideal.
*/
public class Tunnel {
protected static Signature
ConstructSignature( SignatureAlgorithm alg, SignatureSpi engine) {
return new Signature(alg, engine);
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/X509Certificate.java 0000664 0000000 0000000 00000002741 14565430767 0025743 0 ustar 00root root 0000000 0000000 /* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.jss.crypto;
import java.math.BigInteger;
import java.security.Principal;
import java.security.cert.CertificateEncodingException;
/**
* Certificates handled by JSS. All certificates handled by JSS are
* of this type.
*/
public interface X509Certificate
{
/**
* @return The DER encoding of this certificate.
* @throws CertificateEncodingException If an error occurred.
*/
public byte[] getEncoded()
throws CertificateEncodingException;
/**
* @return The nickname of this certificate (could be null).
*/
public abstract String getNickname();
/**
* @return The Public Key from this certificate.
*/
public abstract java.security.PublicKey getPublicKey();
/**
* @return The RFC 1485 ASCII encoding of the Subject Name.
*/
public abstract Principal
getSubjectDN();
/**
* @return The RFC 1485 ASCII encoding of the issuer's Subject Name.
*/
public abstract Principal
getIssuerDN();
/**
* @return The serial number of this certificate.
*/
public abstract BigInteger
getSerialNumber();
/**
* @return the version number of this X.509 certificate.
* 0 means v1, 1 means v2, 2 means v3.
*/
public abstract int
getVersion();
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/crypto/package.html 0000664 0000000 0000000 00000000612 14565430767 0024544 0 ustar 00root root 0000000 0000000
org.mozilla.jss.crypto
Generic cryptographic operations, such as signing and key pair generation.
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/ 0000775 0000000 0000000 00000000000 14565430767 0022546 5 ustar 00root root 0000000 0000000 jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/ 0000775 0000000 0000000 00000000000 14565430767 0024415 5 ustar 00root root 0000000 0000000 jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/extensions/ 0000775 0000000 0000000 00000000000 14565430767 0026614 5 ustar 00root root 0000000 0000000 jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/extensions/AccessDescription.java 0000664 0000000 0000000 00000004770 14565430767 0033074 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.extensions;
import java.io.IOException;
import java.io.Serializable;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
import org.mozilla.jss.netscape.security.util.ObjectIdentifier;
import org.mozilla.jss.netscape.security.x509.GeneralName;
public class AccessDescription implements Serializable {
ObjectIdentifier mOID = null;
GeneralName mLocation = null;
AccessDescription(ObjectIdentifier oid, GeneralName location) {
mOID = oid;
mLocation = location;
}
public ObjectIdentifier getMethod() {
return mOID;
}
public GeneralName getLocation() {
return mLocation;
}
/**
* For serialization:
* Note that GeneralName is not serializable. That is
* why we need to define our own serialization method.
*/
private void writeObject(java.io.ObjectOutputStream out)
throws IOException {
try (DerOutputStream seq = new DerOutputStream();
DerOutputStream tmp = new DerOutputStream()) {
tmp.putOID(mOID);
mLocation.encode(tmp);
seq.write(DerValue.tag_Sequence, tmp);
out.write(seq.toByteArray());
}
}
/**
* For serialization
* Note that GeneralName is not serializable. That is
* why we need to define our own serialization method.
*/
private void readObject(java.io.ObjectInputStream in)
throws IOException {
DerValue val = new DerValue(in);
DerValue seq = val.data.getDerValue();
mOID = seq.getOID();
DerValue derLoc = val.data.getDerValue();
mLocation = new GeneralName(derLoc);
}
}
AuthInfoAccessExtension.java 0000664 0000000 0000000 00000022271 14565430767 0034140 0 ustar 00root root 0000000 0000000 jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/extensions // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.extensions;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.security.cert.CertificateException;
import java.util.Enumeration;
import java.util.Vector;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
import org.mozilla.jss.netscape.security.util.ObjectIdentifier;
import org.mozilla.jss.netscape.security.x509.CertAttrSet;
import org.mozilla.jss.netscape.security.x509.Extension;
import org.mozilla.jss.netscape.security.x509.GeneralName;
import org.mozilla.jss.netscape.security.x509.URIName;
import org.mozilla.jss.netscape.security.util.Utils;
/**
* This represents the authority information access extension
* as defined in RFC2459.
*
* id-pkix OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) dod(6)
* internet(1) security(5) mechanisms(5)
* pkix(7) } }
* id-pe OBJECT IDENTIFIER ::= { id-pkix 1 }
* id-pe-authorityInfoAccess OBJECT IDENTIFIER ::= { id-pe 1 }
* AuthorityInfoAccessSyntax ::= SEQUENCE SIZE (1..MAX) OF AccessDescription
* AccessDescription ::= SEQUENCE {
* accessMethod OBJECT IDENTIFIER,
* accessLocation GeneralName
* }
* id-ad OBJECT IDENTIFIER ::= { id-pkix 48 }
* id-ad-ocsp OBJECT IDENTIFIER ::= { id-ad 1 }
* id-ad-caIssuers OBJECT IDENTIFIER ::= { id-ad 2 }
*
* Need to make sure the following is added to CMS.cfg:
* oidmap.auth_info_access.class=com.netscape.certsrv.cert.AuthInfoAccessExtension
* oidmap.auth_info_access.oid=1.3.6.1.5.5.7.1.1
*
* @author thomask
* @version $Revision$, $Date$
*/
public class AuthInfoAccessExtension extends Extension implements CertAttrSet {
private static final long serialVersionUID = 7373316523212538446L;
public static final String NAME = "AuthInfoAccessExtension";
public static final String NAME2 = "AuthorityInformationAccess";
public static final int OID_OCSP[] = { 1, 3, 6, 1, 5, 5, 7, 48, 1 };
public static final ObjectIdentifier METHOD_OCSP = new
ObjectIdentifier(OID_OCSP);
public static final int OID_CA_ISSUERS[] = { 1, 3, 6, 1, 5, 5, 7, 48, 2 };
public static final ObjectIdentifier METHOD_CA_ISSUERS = new
ObjectIdentifier(OID_CA_ISSUERS);
public static final int OID[] = { 1, 3, 6, 1, 5, 5, 7, 1, 1 };
public static final ObjectIdentifier ID = new ObjectIdentifier(OID);
private Vector mDesc = new Vector<>();
/**
* Create the extension from the passed DER encoded value of the same.
*
* @param critical true if the extension is to be treated as critical.
*/
public AuthInfoAccessExtension(boolean critical) {
this.extensionId = ID;
this.critical = critical;
this.extensionValue = null; // build this when encodeThis() is called
}
/**
* Create the extension from the passed DER encoded value of the same.
*
* @param critical true if the extension is to be treated as critical.
* @param value Array of DER encoded bytes of the actual value.
* @exception IOException on error.
*/
public AuthInfoAccessExtension(Boolean critical, Object value)
throws IOException {
this.extensionId = ID;
this.critical = critical.booleanValue();
this.extensionValue = ((byte[]) value).clone();
decodeThis();
}
/**
* Sets extension attribute.
*/
@Override
public void set(String name, Object obj) throws CertificateException {
// NOT USED
}
/**
* Retrieves extension attribute.
*/
@Override
public Object get(String name) throws CertificateException {
// NOT USED
return null;
}
/**
* Deletes attribute.
*/
@Override
public void delete(String name) throws CertificateException {
// NOT USED
}
/**
* Decodes this extension.
*/
@Override
public void decode(InputStream in) throws IOException {
// NOT USED
}
/**
* Return an enumeration of names of attributes existing within this
* attribute.
*/
@Override
public Enumeration getAttributeNames() {
// NOT USED
return null;
}
/**
* Return the name of this attribute.
*/
@Override
public String getName() {
return NAME;
}
/**
* Adds Access Description.
*/
public void addAccessDescription(
ObjectIdentifier method,
GeneralName gn) {
clearValue();
mDesc.addElement(new AccessDescription(method, gn));
}
public AccessDescription getAccessDescription(int pos) {
return mDesc.elementAt(pos);
}
/**
* Returns the number of access description.
*/
public int numberOfAccessDescription() {
return mDesc.size();
}
private void decodeThis() throws IOException {
DerValue val = new DerValue(this.extensionValue);
if (val.tag != DerValue.tag_Sequence) {
throw new IOException("Invalid encoding of AuthInfoAccess extension");
}
while (val.data.available() != 0) {
DerValue seq = val.data.getDerValue();
ObjectIdentifier method = seq.data.getDerValue().getOID();
GeneralName gn = new GeneralName(seq.data.getDerValue());
addAccessDescription(method, gn);
}
}
private void encodeThis() throws IOException {
try (DerOutputStream seq = new DerOutputStream();
DerOutputStream tmp = new DerOutputStream()) {
for (int i = 0; i < mDesc.size(); i++) {
DerOutputStream tmp0 = new DerOutputStream();
AccessDescription ad = mDesc.elementAt(i);
tmp0.putOID(ad.getMethod());
ad.getLocation().encode(tmp0);
tmp.write(DerValue.tag_Sequence, tmp0);
}
seq.write(DerValue.tag_Sequence, tmp);
this.extensionValue = seq.toByteArray();
}
}
/**
* Write the extension to the DerOutputStream.
*
* @param out the DerOutputStream to write the extension to.
* @exception IOException on encoding errors.
*/
@Override
public void encode(OutputStream out) throws IOException {
DerOutputStream tmp = new DerOutputStream();
if (this.extensionValue == null) {
encodeThis();
}
super.encode(tmp);
out.write(tmp.toByteArray());
}
/**
* Returns a printable representation of the AuthInfoAccess.
*/
@Override
public String toString() {
StringBuffer s = new StringBuffer();
String b = super.toString() + "AuthInfoAccess [\n";
s.append(b);
for (int i = 0; i < mDesc.size(); i++) {
AccessDescription ad = mDesc.elementAt(i);
s.append("(" + i + ")");
s.append(" ");
s.append(ad.getMethod().toString() + " " + ad.getLocation().toString());
}
return (s.toString() + "]\n");
}
public static void main(String[] argv) {
AuthInfoAccessExtension aia = new AuthInfoAccessExtension(false);
GeneralName ocspName = new GeneralName(new
URIName("http://ocsp.netscape.com"));
aia.addAccessDescription(METHOD_OCSP, ocspName);
GeneralName caIssuersName = new GeneralName(new
URIName("http://ocsp.netscape.com"));
aia.addAccessDescription(METHOD_CA_ISSUERS, caIssuersName);
ByteArrayOutputStream os = new ByteArrayOutputStream();
try {
aia.encode(os);
System.out.println(Utils.base64encode(os.toByteArray(), true));
} catch (IOException e) {
System.out.println(e.toString());
}
try {
// test serialization
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(aia);
ByteArrayInputStream bis = new ByteArrayInputStream(
bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
AuthInfoAccessExtension clone = (AuthInfoAccessExtension)
ois.readObject();
System.out.println(clone);
} catch (Exception e) {
System.out.println(e.toString());
}
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/extensions/CertInfo.java 0000664 0000000 0000000 00000011724 14565430767 0031175 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.extensions;
import java.io.IOException;
import java.math.BigInteger;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.util.Date;
import org.mozilla.jss.netscape.security.x509.AlgorithmId;
import org.mozilla.jss.netscape.security.x509.CertificateAlgorithmId;
import org.mozilla.jss.netscape.security.x509.CertificateIssuerName;
import org.mozilla.jss.netscape.security.x509.CertificateSerialNumber;
import org.mozilla.jss.netscape.security.x509.CertificateSubjectName;
import org.mozilla.jss.netscape.security.x509.CertificateValidity;
import org.mozilla.jss.netscape.security.x509.CertificateVersion;
import org.mozilla.jss.netscape.security.x509.X500Name;
import org.mozilla.jss.netscape.security.x509.X509CertInfo;
/**
* Extends X509CertInfo class so that minimal fields are initialized at
* creation time so an object of this type is always serializable.
*/
public class CertInfo extends X509CertInfo {
/**
*
*/
private static final long serialVersionUID = -2883888348288591989L;
public static final CertificateSubjectName SERIALIZE_SUBJECT;
public static final CertificateIssuerName SERIALIZE_ISSUER;
public static final CertificateValidity SERIALIZE_VALIDITY;
public static final CertificateSerialNumber SERIALIZE_SERIALNO;
public static final CertificateAlgorithmId SERIALIZE_ALGOR;
public static final CertificateVersion FORCE_VERSION_3;
static {
try {
// force version 3
FORCE_VERSION_3 =
new CertificateVersion(CertificateVersion.V3);
SERIALIZE_SUBJECT =
new CertificateSubjectName(
new X500Name("cn=uninitialized"));
SERIALIZE_ISSUER =
new CertificateIssuerName(
new X500Name("cn=uninitialized"));
SERIALIZE_VALIDITY =
new CertificateValidity(new Date(0), new Date(0));
SERIALIZE_SERIALNO =
new CertificateSerialNumber(new BigInteger("0"));
SERIALIZE_ALGOR =
new CertificateAlgorithmId(AlgorithmId.get("MD5withRSA"));
} catch (IOException e) {
// should never happen. If does, system is hosed.
System.out.println("**** Impossible Error encountered ****");
throw new RuntimeException(e.toString());
} catch (NoSuchAlgorithmException e) {
// should never happen. If does, system is hosed.
System.out.println("**** Impossible Error encountered ****");
throw new RuntimeException(e.toString());
}
}
/**
* Initializes most fields required by der encoding so object will
* serialize properly.
*/
// XXX should write a class to use something else for serialization
// but this is faster and done now for the time crunch.
public CertInfo() {
super();
makeSerializable(this);
}
public static void makeSerializable(X509CertInfo certinfo) {
try {
// force version 3.
certinfo.set(X509CertInfo.VERSION, FORCE_VERSION_3);
if (certinfo.get(X509CertInfo.SERIAL_NUMBER) == null) {
certinfo.set(X509CertInfo.SERIAL_NUMBER, SERIALIZE_SERIALNO);
}
if (certinfo.get(X509CertInfo.ALGORITHM_ID) == null) {
certinfo.set(X509CertInfo.ALGORITHM_ID, SERIALIZE_ALGOR);
}
if (certinfo.get(X509CertInfo.ISSUER) == null) {
certinfo.set(X509CertInfo.ISSUER, SERIALIZE_ISSUER);
}
if (certinfo.get(X509CertInfo.VALIDITY) == null) {
certinfo.set(X509CertInfo.VALIDITY, SERIALIZE_VALIDITY);
}
// set subject name anyway - it'll get overwritten.
if (certinfo.get(X509CertInfo.SUBJECT) == null) {
certinfo.set(X509CertInfo.SUBJECT, SERIALIZE_SUBJECT);
}
// key is set later in the request.
} // these exceptions shouldn't happen here unless the
// whole process is hosed.
catch (CertificateException e) {
} catch (IOException e) {
}
}
}
CertificateRenewalWindowExtension.java 0000664 0000000 0000000 00000013306 14565430767 0036230 0 ustar 00root root 0000000 0000000 jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/extensions // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.extensions;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.cert.CertificateException;
import java.util.Date;
import java.util.Enumeration;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
import org.mozilla.jss.netscape.security.util.ObjectIdentifier;
import org.mozilla.jss.netscape.security.x509.CertAttrSet;
import org.mozilla.jss.netscape.security.x509.Extension;
/**
* This represents the CertificateRenewalWindow extension
* as defined in draft-thayes-cert-renewal-00
*
* CertificateRenewalWindow ::= SEQUENCE {
* beginTime GeneralizedTime,
* endTime GeneralizedTime OPTIONAL }
*
* @author thomask
* @version $Revision$, $Date$
*/
public class CertificateRenewalWindowExtension extends Extension
implements CertAttrSet {
private static final long serialVersionUID = 4470220533545299271L;
public static final String NAME = "CertificateRenewalWindow";
public static final int OID[] = { 2, 16, 840, 1, 113730, 1, 15 };
public static final ObjectIdentifier ID = new ObjectIdentifier(OID);
private Date mBeginTime = null;
private Date mEndTime = null; // optional
public CertificateRenewalWindowExtension(boolean critical, Date beginTime,
Date endTime) throws IOException {
this.extensionId = ID;
this.critical = critical;
mBeginTime = beginTime;
mEndTime = endTime;
encodeThis();
}
public CertificateRenewalWindowExtension(boolean critical) {
this.extensionId = ID;
this.critical = critical;
this.extensionValue = null; // build this when encodeThis() is called
}
public CertificateRenewalWindowExtension(Boolean critical, Object value)
throws IOException {
this.extensionId = ID;
this.critical = critical.booleanValue();
this.extensionValue = ((byte[]) value).clone();
decodeThis();
}
@Override
public String getName() {
return NAME;
}
/**
* Sets extension attribute.
*/
@Override
public void set(String name, Object obj) throws CertificateException {
// NOT USED
}
/**
* Retrieves extension attribute.
*/
@Override
public Object get(String name) throws CertificateException {
// NOT USED
return null;
}
/**
* Deletes attribute.
*/
@Override
public void delete(String name) throws CertificateException {
// NOT USED
}
/**
* Decodes this extension.
*/
@Override
public void decode(InputStream in) throws IOException {
// NOT USED
}
/**
* Return an enumeration of names of attributes existing within this
* attribute.
*/
@Override
public Enumeration getAttributeNames() {
// NOT USED
return null;
}
public Date getBeginTime() {
return mBeginTime;
}
public Date getEndTime() {
return mEndTime;
}
public void setBeginTime(Date d) {
mBeginTime = d;
}
public void setEndTime(Date d) {
mEndTime = d;
}
private void decodeThis() throws IOException {
DerValue val = new DerValue(this.extensionValue);
if (val.tag != DerValue.tag_Sequence) {
throw new IOException("Invalid encoding of CertificateWindow extension");
}
while (val.data.available() != 0) {
if (mBeginTime == null) {
mBeginTime = val.data.getGeneralizedTime();
} else {
mEndTime = val.data.getGeneralizedTime();
}
}
}
private void encodeThis() throws IOException {
try (DerOutputStream seq = new DerOutputStream();
DerOutputStream tmp = new DerOutputStream()) {
tmp.putGeneralizedTime(mBeginTime);
if (mEndTime != null) {
tmp.putGeneralizedTime(mEndTime);
}
seq.write(DerValue.tag_Sequence, tmp);
this.extensionValue = seq.toByteArray();
}
}
/**
* Write the extension to the DerOutputStream.
*
* @param out the DerOutputStream to write the extension to.
* @exception IOException on encoding errors.
*/
@Override
public void encode(OutputStream out) throws IOException {
DerOutputStream tmp = new DerOutputStream();
if (this.extensionValue == null) {
encodeThis();
}
super.encode(tmp);
out.write(tmp.toByteArray());
}
/**
* Returns a printable representation of the CertificateRenewalWindow.
*/
@Override
public String toString() {
String s = super.toString() + "CertificateRenewalWindow [\n";
s += "BeginTime: " + mBeginTime + "\n";
if (mEndTime != null) {
s += "EndTime: " + mEndTime;
}
return (s + "]\n");
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/extensions/CertificateScopeEntry.java0000664 0000000 0000000 00000005712 14565430767 0033722 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.extensions;
import java.io.IOException;
import org.mozilla.jss.netscape.security.util.BigInt;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
import org.mozilla.jss.netscape.security.x509.GeneralName;
/**
* This represents the CertificateScopeOfUse extension
* as defined in draft-thayes-cert-scope-00
*
* CertificateScopeEntry ::= SEQUENCE {
* name GeneralName, -- pattern, as for NameConstraints
* portNumber INTEGER OPTIONAL
* }
* CertificateScopeOfUse ::= SEQUENCE OF CertificateScopeEntry
*
* @author thomask
* @version $Revision$, $Date$
*/
public class CertificateScopeEntry {
private GeneralName mGn = null;
private BigInt mPort = null;
/**
* Constructs scope with der value.
*/
public CertificateScopeEntry(DerValue val) throws IOException {
if (val.tag != DerValue.tag_Sequence) {
throw new IOException("Invalid encoding for PolicyQualifierInfo.");
}
DerValue gn = val.data.getDerValue();
mGn = new GeneralName(gn);
if (val.data.available() != 0) {
mPort = val.data.getInteger();
}
}
/**
* Constructs scope wit
*/
public CertificateScopeEntry(GeneralName gn, BigInt port) {
mGn = gn;
mPort = port; // optional
}
public void encode(DerOutputStream out) throws IOException {
DerOutputStream tmp = new DerOutputStream();
mGn.encode(tmp);
if (mPort != null) {
tmp.putInteger(mPort);
}
out.write(DerValue.tag_Sequence, tmp);
}
/**
* Returns a GeneralName
*/
public GeneralName getGeneralName() {
return mGn;
}
/**
* Returns a port
*/
public BigInt getPort() {
return mPort;
}
/**
* Returns a printable representation of the CertificateRenewalWindow.
*/
@Override
public String toString() {
String s = super.toString() + "CertificateScopeEntry [\n";
s += "GeneralName: " + mGn;
if (mPort != null) {
s += "PortNumber: " + mPort;
}
return (s + "]\n");
}
}
CertificateScopeOfUseExtension.java 0000664 0000000 0000000 00000014155 14565430767 0035461 0 ustar 00root root 0000000 0000000 jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/extensions // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.extensions;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.cert.CertificateException;
import java.util.Enumeration;
import java.util.Vector;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
import org.mozilla.jss.netscape.security.util.ObjectIdentifier;
import org.mozilla.jss.netscape.security.x509.CertAttrSet;
import org.mozilla.jss.netscape.security.x509.Extension;
import org.mozilla.jss.netscape.security.x509.OIDMap;
/**
* This represents the CertificateScopeOfUse extension
* as defined in draft-thayes-cert-scope-00
*
* CertificateScopeEntry ::= SEQUENCE {
* name GeneralName, -- pattern, as for NameConstraints
* portNumber INTEGER OPTIONAL
* }
* CertificateScopeOfUse ::= SEQUENCE OF CertificateScopeEntry
*
* @author thomask
* @version $Revision$, $Date$
*/
public class CertificateScopeOfUseExtension extends Extension
implements CertAttrSet {
/**
*
*/
private static final long serialVersionUID = 2143292831971567770L;
public static final String NAME = "CertificateScopeOfUse";
public static final int OID[] = { 2, 16, 840, 1, 113730, 1, 17 };
public static final ObjectIdentifier ID = new ObjectIdentifier(OID);
private Vector mEntries = null;
static {
try {
OIDMap.addAttribute(CertificateScopeOfUseExtension.class.getName(),
ID.toString(), NAME);
} catch (CertificateException e) {
}
}
public CertificateScopeOfUseExtension(boolean critical, Vector scopeEntries)
throws IOException {
this.extensionId = ID;
this.critical = critical;
this.extensionValue = null; // build this when encodeThis() is called
mEntries = scopeEntries;
encodeThis();
}
public CertificateScopeOfUseExtension(boolean critical) {
this.extensionId = ID;
this.critical = critical;
this.extensionValue = null; // build this when encodeThis() is called
}
public CertificateScopeOfUseExtension(Boolean critical, Object value)
throws IOException {
this.extensionId = ID;
this.critical = critical.booleanValue();
this.extensionValue = ((byte[]) value).clone();
decodeThis();
}
@Override
public String getName() {
return NAME;
}
public Vector getCertificateScopeEntries() {
return mEntries;
}
/**
* Sets extension attribute.
*/
@Override
public void set(String name, Object obj) throws CertificateException {
// NOT USED
}
/**
* Retrieves extension attribute.
*/
@Override
public Object get(String name) throws CertificateException {
// NOT USED
return null;
}
/**
* Deletes attribute.
*/
@Override
public void delete(String name) throws CertificateException {
// NOT USED
}
/**
* Decodes this extension.
*/
@Override
public void decode(InputStream in) throws IOException {
// NOT USED
}
/**
* Return an enumeration of names of attributes existing within this
* attribute.
*/
@Override
public Enumeration getAttributeNames() {
// NOT USED
return null;
}
private void decodeThis() throws IOException {
DerValue val = new DerValue(this.extensionValue);
if (val.tag != DerValue.tag_Sequence) {
throw new IOException("Invalid encoding of CertificateWindow extension");
}
mEntries = new Vector<>();
while (val.data.available() != 0) {
mEntries.addElement(new CertificateScopeEntry(
val.data.getDerValue()));
}
}
private void encodeThis() throws IOException {
try (DerOutputStream seq = new DerOutputStream();
DerOutputStream tmp = new DerOutputStream()) {
if (mEntries == null)
throw new IOException("Invalid Scope Entries");
for (int i = 0; i < mEntries.size(); i++) {
CertificateScopeEntry se = mEntries.elementAt(i);
se.encode(tmp);
}
seq.write(DerValue.tag_Sequence, tmp);
this.extensionValue = seq.toByteArray();
}
}
/**
* Write the extension to the DerOutputStream.
*
* @param out the DerOutputStream to write the extension to.
* @exception IOException on encoding errors.
*/
@Override
public void encode(OutputStream out) throws IOException {
DerOutputStream tmp = new DerOutputStream();
if (this.extensionValue == null) {
encodeThis();
}
super.encode(tmp);
out.write(tmp.toByteArray());
}
/**
* Returns a printable representation of the CertificateRenewalWindow.
*/
@Override
public String toString() {
StringBuffer s = new StringBuffer(super.toString() + "CertificateUseOfScope [\n");
if (mEntries != null) {
for (int i = 0; i < mEntries.size(); i++) {
CertificateScopeEntry se = mEntries.elementAt(i);
s.append(se.toString());
}
}
return (s.toString() + "]\n");
}
}
ExtendedKeyUsageExtension.java 0000664 0000000 0000000 00000016066 14565430767 0034504 0 ustar 00root root 0000000 0000000 jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/extensions // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.extensions;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.cert.CertificateException;
import java.util.Enumeration;
import java.util.Vector;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
import org.mozilla.jss.netscape.security.util.ObjectIdentifier;
import org.mozilla.jss.netscape.security.x509.CertAttrSet;
import org.mozilla.jss.netscape.security.x509.Extension;
import org.mozilla.jss.netscape.security.x509.OIDMap;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This represents the extended key usage extension.
*/
public class ExtendedKeyUsageExtension extends Extension implements CertAttrSet {
/**
*
*/
private static final long serialVersionUID = 765403075764697489L;
private static final Logger logger = LoggerFactory.getLogger(ExtendedKeyUsageExtension.class);
public static final String OID = "2.5.29.37";
public static final String NAME = OIDMap.EXT_KEY_USAGE_NAME;
public static final String OID_OCSPSigning = "1.3.6.1.5.5.7.3.9";
public static final String OID_CODESigning = "1.3.6.1.5.5.7.3.3";
public static final int OID_OCSP_SIGNING_STR[] =
{ 1, 3, 6, 1, 5, 5, 7, 3, 9 };
public static final ObjectIdentifier OID_OCSP_SIGNING = new
ObjectIdentifier(OID_OCSP_SIGNING_STR);
public static final int OID_CODE_SIGNING_STR[] =
{ 1, 3, 6, 1, 5, 5, 7, 3, 3 };
public static final ObjectIdentifier OID_CODE_SIGNING = new
ObjectIdentifier(OID_OCSP_SIGNING_STR);
private Vector oidSet = null;
private byte mCached[] = null;
static {
try {
OIDMap.addAttribute(ExtendedKeyUsageExtension.class.getName(),
OID, ExtendedKeyUsageExtension.NAME);
} catch (CertificateException e) {
}
}
public ExtendedKeyUsageExtension() throws IOException {
this(false, null);
}
public ExtendedKeyUsageExtension(boolean crit, Vector oids) throws IOException {
try {
extensionId = ObjectIdentifier.getObjectIdentifier(OID);
} catch (IOException e) {
// never here
}
critical = crit;
if (oids != null) {
oidSet = new Vector<>(oids);
} else {
oidSet = new Vector<>();
}
encodeExtValue();
}
public ExtendedKeyUsageExtension(Boolean crit, Object byteVal)
throws IOException {
extensionId = ObjectIdentifier.getObjectIdentifier(OID);
critical = crit.booleanValue();
extensionValue = ((byte[]) byteVal).clone();
decodeThis();
}
@Override
public void setCritical(boolean newValue) {
if (critical != newValue) {
critical = newValue;
mCached = null;
}
}
public Enumeration getOIDs() {
if (oidSet == null)
return null;
return oidSet.elements();
}
public void deleteAllOIDs() {
if (oidSet == null)
return;
oidSet.clear();
}
public void addOID(ObjectIdentifier oid) {
if (oidSet == null) {
oidSet = new Vector<>();
}
if (oidSet.contains(oid))
return;
oidSet.addElement(oid);
mCached = null;
}
@Override
public void encode(DerOutputStream out) throws IOException {
if (mCached == null) {
encodeExtValue();
super.encode(out);
mCached = out.toByteArray();
}
}
@Override
public String toString() {
String presentation = "oid=" + ExtendedKeyUsageExtension.OID + " ";
if (critical) {
presentation += "critical=true";
}
if (extensionValue != null) {
StringBuffer extByteValue = new StringBuffer(" val=");
for (int i = 0; i < extensionValue.length; i++) {
extByteValue.append(extensionValue[i] + " ");
}
presentation += extByteValue.toString();
}
return presentation;
}
@Override
public void decode(InputStream in)
throws CertificateException, IOException {
}
@Override
public void encode(OutputStream out)
throws CertificateException, IOException {
if (mCached == null) {
DerOutputStream temp = new DerOutputStream();
encode(temp);
}
out.write(mCached);
}
@Override
public void set(String name, Object obj)
throws CertificateException, IOException {
// NOT USED
}
@Override
public Object get(String name) throws CertificateException, IOException {
// NOT USED
return null;
}
@Override
public Enumeration getAttributeNames() {
return null;
}
@Override
public String getName() {
return NAME;
}
@Override
public void delete(String name)
throws CertificateException, IOException {
// NOT USED
}
private void decodeThis() throws IOException {
DerValue val = new DerValue(this.extensionValue);
if (val.tag != DerValue.tag_Sequence) {
throw new IOException("Invalid encoding of AuthInfoAccess extension");
}
if (oidSet == null)
oidSet = new Vector<>();
while (val.data.available() != 0) {
DerValue oidVal = val.data.getDerValue();
oidSet.addElement(oidVal.getOID());
}
}
private void encodeExtValue() throws IOException {
DerOutputStream out = new DerOutputStream();
DerOutputStream temp = new DerOutputStream();
if (!oidSet.isEmpty()) {
Enumeration oidList = oidSet.elements();
try {
while (oidList.hasMoreElements()) {
temp.putOID(oidList.nextElement());
}
} catch (IOException ex) {
logger.error("Problem encoding", ex);
}
}
try {
out.write(DerValue.tag_Sequence, temp);
} catch (IOException ex) {
} finally {
out.close();
}
extensionValue = out.toByteArray();
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/extensions/GenericASN1Extension.java 0000664 0000000 0000000 00000037073 14565430767 0033365 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.extensions;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Array;
import java.security.cert.CertificateException;
import java.text.DateFormat;
import java.text.ParseException;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.StringTokenizer;
import java.util.Vector;
import org.mozilla.jss.netscape.security.util.BigInt;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
import org.mozilla.jss.netscape.security.util.ObjectIdentifier;
import org.mozilla.jss.netscape.security.x509.CertAttrSet;
import org.mozilla.jss.netscape.security.x509.Extension;
import org.mozilla.jss.netscape.security.x509.OIDMap;
/**
* Represent the AsnInteger Extension.
*/
public class GenericASN1Extension extends Extension
implements CertAttrSet {
/**
*
*/
private static final long serialVersionUID = 8047548816784949009L;
protected static final int MAX_ATTR = 10;
protected static final String PROP_CRITICAL =
"critical";
protected static final String PROP_NAME =
"name";
protected static final String PROP_OID =
"oid";
protected static final String PROP_PATTERN =
"pattern";
protected static final String PROP_ATTRIBUTE =
"attribute";
protected static final String PROP_TYPE =
"type";
protected static final String PROP_SOURCE =
"source";
protected static final String PROP_VALUE =
"value";
protected static final String PROP_PREDICATE =
"predicate";
/**
* Identifier for this attribute, to be used with the
* get, set, delete methods of Certificate, x509 type.
*/
private String name;
public String OID = null;
public static Hashtable mConfig = null;
public String pattern = null;
private int index = 0;
// Encode this value
private void encodeThis()
throws IOException, ParseException {
this.extensionValue = encodePattern();
}
// Encode pattern
private byte[] encodePattern()
throws IOException, ParseException {
DerOutputStream tmp = new DerOutputStream();
String type = null;
String value = null;
String source = null;
while (index < pattern.length()) {
char ch = pattern.charAt(index);
switch (ch) {
case '{':
index++;
byte[] buff = encodePattern();
tmp.putDerValue(new DerValue(buff));
break;
case '}':
try (DerOutputStream os = new DerOutputStream()) {
os.write(DerValue.tag_Sequence, tmp);
return os.toByteArray();
}
default:
type = mConfig.get(PROP_ATTRIBUTE + "." + ch + "." + PROP_TYPE);
if (type.equalsIgnoreCase("integer")) {
int num = Integer.parseInt(mConfig.get(PROP_ATTRIBUTE + "." + ch + "." + PROP_VALUE));
PutInteger(tmp, num);
} else if (type.equalsIgnoreCase("ia5string")) {
source = mConfig.get(PROP_ATTRIBUTE + "." + ch + "." + PROP_SOURCE);
value = mConfig.get(PROP_ATTRIBUTE + "." + ch + "." + PROP_VALUE);
if (source.equalsIgnoreCase("file"))
PutIA5String(tmp, getFromFile(value));
else
PutIA5String(tmp, value);
} else if (type.equalsIgnoreCase("octetstring")) {
source = mConfig.get(PROP_ATTRIBUTE + "." + ch + "." + PROP_SOURCE);
value = mConfig.get(PROP_ATTRIBUTE + "." + ch + "." + PROP_VALUE);
// It should be colon seperated ASCII Hexdecimal String
if (source.equalsIgnoreCase("file"))
PutOctetString(tmp, getFromFile(value));
else
PutOctetString(tmp, value);
} else if (type.equalsIgnoreCase("bmpstring")) {
source = mConfig.get(PROP_ATTRIBUTE + "." + ch + "." + PROP_SOURCE);
value = mConfig.get(PROP_ATTRIBUTE + "." + ch + "." + PROP_VALUE);
if (source.equalsIgnoreCase("file"))
PutBMPString(tmp, getFromFile(value));
else
PutBMPString(tmp, value);
} else if (type.equalsIgnoreCase("printablestring")) {
source = mConfig.get(PROP_ATTRIBUTE + "." + ch + "." + PROP_SOURCE);
value = mConfig.get(PROP_ATTRIBUTE + "." + ch + "." + PROP_VALUE);
if (source.equalsIgnoreCase("file"))
PutPrintableString(tmp, getFromFile(value));
else
PutPrintableString(tmp, value);
} else if (type.equalsIgnoreCase("visiblestring")) {
source = mConfig.get(PROP_ATTRIBUTE + "." + ch + "." + PROP_SOURCE);
value = mConfig.get(PROP_ATTRIBUTE + "." + ch + "." + PROP_VALUE);
if (source.equalsIgnoreCase("file"))
PutVisibleString(tmp, getFromFile(value));
else
PutVisibleString(tmp, value);
} else if (type.equalsIgnoreCase("utctime")) {
value = mConfig.get(PROP_ATTRIBUTE + "." + ch + "." + PROP_VALUE);
PutUTCtime(tmp, value);
} else if (type.equalsIgnoreCase("oid")) {
value = mConfig.get(PROP_ATTRIBUTE + "." + ch + "." + PROP_VALUE);
PutOID(tmp, value);
} else if (type.equalsIgnoreCase("boolean")) {
boolean bool = false;
String b = mConfig.get(PROP_ATTRIBUTE + "." + ch + "." + PROP_VALUE);
if (b.equalsIgnoreCase("true"))
bool = true;
else
bool = false;
PutBoolean(tmp, bool);
} else if (type.equalsIgnoreCase("null")) {
tmp.putNull();
} else {
throw new ParseException("Unknown Attribute Type", 0);
}
}
index++;
}
return tmp.toByteArray();
}
/**
* Create a GenericASN1Extension with the value and oid.
* The criticality is set to false.
*
* @param name the name of this extension
* @param oid the object identifier of this extension
* @param pattern to use for encoding this extension
* @param critical true if the extension should be treated as critical
* @param config additional configuration for this extension
*/
public GenericASN1Extension(String name, String oid, String pattern, boolean critical,
Hashtable config)
throws IOException, ParseException {
ObjectIdentifier tmpid = new ObjectIdentifier(oid);
this.name = name;
OID = oid;
mConfig = config;
this.pattern = pattern;
try {
if (OIDMap.getName(tmpid) == null)
OIDMap.addAttribute("org.mozilla.jss.netscape.security.x509.GenericASN1Extension", oid, name);
} catch (CertificateException e) {
}
this.extensionId = tmpid;
this.critical = critical;
encodeThis();
}
/**
* Create a GenericASN1Extension with the value and oid.
* The criticality is set to false.
*
* @param config the values to be set for the extension.
*/
public GenericASN1Extension(Hashtable config)
throws IOException, ParseException {
mConfig = config;
ObjectIdentifier tmpid = new ObjectIdentifier(mConfig.get(PROP_OID));
name = mConfig.get(PROP_NAME);
OID = mConfig.get(PROP_OID);
pattern = mConfig.get(PROP_PATTERN);
try {
if (OIDMap.getName(tmpid) == null)
OIDMap.addAttribute("GenericASN1Extension", OID, name);
} catch (CertificateException e) {
}
this.extensionId = tmpid;
this.critical = false;
String b = mConfig.get(PROP_CRITICAL);
if (b.equalsIgnoreCase("true"))
this.critical = true;
else
this.critical = false;
encodeThis();
}
/**
* Create the extension from the passed DER encoded value of the same.
*
* @param critical true if the extension is to be treated as critical.
* @param value Array of DER encoded bytes of the actual value.
* @exception IOException on error.
*/
public GenericASN1Extension(Boolean critical, Object value)
throws IOException {
this.extensionId = new ObjectIdentifier(OID);
this.critical = critical.booleanValue();
int len = Array.getLength(value);
byte[] extValue = new byte[len];
for (int i = 0; i < len; i++) {
extValue[i] = Array.getByte(value, i);
}
this.extensionValue = extValue;
}
/**
* Set the attribute value.
*/
@Override
public void set(String name, Object obj) throws IOException {
throw new IOException("Method not to be called directly.");
}
/**
* Get the attribute value.
*/
@Override
public Object get(String name) throws IOException {
return null;
}
/**
* Delete the attribute value.
*/
@Override
public void delete(String name) throws IOException {
throw new IOException("Method not to be called directly.");
}
/**
* Returns a printable representation of the GenericASN1Extension.
*/
@Override
public String toString() {
return "";
}
/**
* Decode the extension from the InputStream.
*
* @param in the InputStream to unmarshal the contents from.
* @exception IOException on decoding or validity errors.
*/
@Override
public void decode(InputStream in) throws IOException {
throw new IOException("Method not to be called directly.");
}
/**
* Write the extension to the DerOutputStream.
*
* @param out the DerOutputStream to write the extension to.
* @exception IOException on encoding errors.
*/
@Override
public void encode(OutputStream out)
throws IOException {
DerOutputStream tmp = new DerOutputStream();
try {
if (this.extensionValue == null) {
this.extensionId = new ObjectIdentifier(OID);
this.critical = true;
encodeThis();
}
} catch (ParseException e) {
}
super.encode(tmp);
out.write(tmp.toByteArray());
}
/**
* Return the name of this attribute.
*/
@Override
public String getName() {
return name;
}
/**
* Set the name of this attribute.
*/
public void setName(String name) {
this.name = name;
}
/**
* Return the OID of this attribute.
*/
public String getOID() {
return OID;
}
/**
* Set the OID of this attribute.
*/
public void setOID(String oid) {
OID = oid;
}
/**
* Return an enumeration of names of attributes existing within this
* attribute.
*/
@Override
public Enumeration getAttributeNames() {
Vector elements = new Vector<>();
elements.addElement("octet");
return (elements.elements());
}
private void PutInteger(DerOutputStream os, int number)
throws IOException, ParseException {
os.putInteger(new BigInt(number));
return;
}
private void PutIA5String(DerOutputStream os, String value)
throws IOException, ParseException {
os.putIA5String(value);
return;
}
private void PutOctetString(DerOutputStream os, String value)
throws IOException, ParseException {
StringTokenizer token = new StringTokenizer(value, ":");
byte[] octets = new byte[token.countTokens()];
for (int i = 0; token.hasMoreElements(); i++) {
String num = (String) token.nextElement();
octets[i] = (byte) Integer.parseInt(num, 16);
}
os.putOctetString(octets);
return;
}
private void PutBMPString(DerOutputStream os, String value)
throws IOException, ParseException {
os.putBMPString(value);
return;
}
private void PutPrintableString(DerOutputStream os, String value)
throws IOException, ParseException {
os.putPrintableString(value);
return;
}
private void PutVisibleString(DerOutputStream os, String value)
throws IOException, ParseException {
os.putVisibleString(value);
return;
}
private void PutUTCtime(DerOutputStream os, String value)
throws IOException, ParseException {
DateFormat df = DateFormat.getDateInstance(DateFormat.SHORT);
os.putUTCTime(df.parse(value));
return;
}
private void PutOID(DerOutputStream os, String value)
throws IOException, ParseException {
os.putOID(new ObjectIdentifier(value));
return;
}
private void PutBoolean(DerOutputStream os, boolean value)
throws IOException, ParseException {
os.putBoolean(value);
return;
}
private String getFromFile(String fname) throws IOException {
String s = null;
byte[] buff = null;
int i = 0;
int j = 0;
if ((fname == null) || (fname.equals(""))) {
throw new IOException("File name is not provided.");
}
FileInputStream fis = null;
try {
fis = new FileInputStream(fname);
int n = 0;
while ((n = fis.available()) > 0) {
buff = new byte[n];
int result = fis.read(buff);
if (result == -1)
break;
s = new String(buff);
}
} finally {
if (fis != null) {
fis.close();
}
}
if (s == null) {
return "";
}
for (i = 0, j = 0; j < s.length(); j++) {
int ch = s.charAt(j);
if (ch == 10 || ch == 13 || ch == 9)
continue;
i++;
}
buff = new byte[i];
for (i = 0, j = 0; j < s.length(); j++) {
int ch = s.charAt(j);
if (ch == 10 || ch == 13 || ch == 9)
continue;
buff[i++] = (byte) ch;
}
s = new String(buff);
return s;
}
}
InhibitAnyPolicyExtension.java 0000664 0000000 0000000 00000012654 14565430767 0034523 0 ustar 00root root 0000000 0000000 jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/extensions // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.extensions;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Array;
import java.security.cert.CertificateException;
import java.util.Enumeration;
import org.mozilla.jss.netscape.security.util.BigInt;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
import org.mozilla.jss.netscape.security.util.ObjectIdentifier;
import org.mozilla.jss.netscape.security.x509.CertAttrSet;
import org.mozilla.jss.netscape.security.x509.Extension;
import org.mozilla.jss.netscape.security.x509.OIDMap;
/**
* RFC3280:
*
* id-ce-inhibitAnyPolicy OBJECT IDENTIFIER ::= { id-ce 54 }
*
* InhibitAnyPolicy ::= SkipCerts
*
* SkipCerts ::= INTEGER (0..MAX)
*/
public class InhibitAnyPolicyExtension
extends Extension implements CertAttrSet {
/**
*
*/
private static final long serialVersionUID = -8963439897419343166L;
public static final String OID = "2.5.29.54";
public static final String NAME = OIDMap.EXT_INHIBIT_ANY_POLICY_NAME;
private BigInt mSkipCerts = new BigInt(-1);
static {
try {
OIDMap.addAttribute(InhibitAnyPolicyExtension.class.getName(),
OID, NAME);
} catch (CertificateException e) {
}
}
public InhibitAnyPolicyExtension() throws IOException {
this(false, null);
}
public InhibitAnyPolicyExtension(boolean crit, BigInt skipCerts) throws IOException {
try {
extensionId = ObjectIdentifier.getObjectIdentifier(OID);
} catch (IOException e) {
// never here
}
critical = crit;
mSkipCerts = skipCerts;
encodeExtValue();
}
public InhibitAnyPolicyExtension(Boolean crit, Object value)
throws IOException {
extensionId = ObjectIdentifier.getObjectIdentifier(OID);
critical = crit.booleanValue();
//extensionValue = (byte[]) ((byte[]) byteVal).clone();
int len = Array.getLength(value);
byte[] extValue = new byte[len];
for (int i = 0; i < len; i++) {
extValue[i] = Array.getByte(value, i);
}
extensionValue = extValue;
decodeThis();
}
@Override
public void setCritical(boolean newValue) {
if (critical != newValue) {
critical = newValue;
}
}
public BigInt getSkipCerts() {
return mSkipCerts;
}
@Override
public String toString() {
String presentation = "ObjectId: " + OID + " ";
if (critical) {
presentation += "Criticality=true";
} else {
presentation += "Criticality=false";
}
if (extensionValue != null) {
String extByteValue = " skipCerts=" + mSkipCerts;
presentation += extByteValue;
}
return presentation;
}
@Override
public void decode(InputStream in)
throws CertificateException, IOException {
}
@Override
public void set(String name, Object obj)
throws CertificateException, IOException {
// NOT USED
}
@Override
public Object get(String name) throws CertificateException, IOException {
// NOT USED
return null;
}
@Override
public Enumeration getAttributeNames() {
return null;
}
@Override
public String getName() {
return NAME;
}
@Override
public void delete(String name)
throws CertificateException, IOException {
// NOT USED
}
private void decodeThis() throws IOException {
DerValue val = new DerValue(this.extensionValue);
mSkipCerts = val.getInteger();
}
@Override
public void encode(OutputStream out) throws IOException {
try (DerOutputStream os = new DerOutputStream()) {
DerOutputStream tmp = new DerOutputStream();
if (this.extensionValue == null) {
try {
extensionId = ObjectIdentifier.getObjectIdentifier(OID);
} catch (IOException e) {
// never here
}
os.putInteger(mSkipCerts);
this.extensionValue = os.toByteArray();
}
super.encode(tmp);
out.write(tmp.toByteArray());
}
}
private void encodeExtValue() throws IOException {
DerOutputStream out = new DerOutputStream();
try {
out.putInteger(mSkipCerts);
} catch (IOException e) {
} finally {
out.close();
}
extensionValue = out.toByteArray();
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/extensions/KerberosName.java 0000664 0000000 0000000 00000011377 14565430767 0032045 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.extensions;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Vector;
import org.mozilla.jss.netscape.security.util.BigInt;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
import org.mozilla.jss.netscape.security.util.ObjectIdentifier;
/**
* This represents a KerberosName as defined in
* RFC 1510.
*
* KerberosName ::= SEQUENCE {
* realm [0] Realm,
* principalName [1] CertPrincipalName -- defined above
* }
*
* CertPrincipalName ::= SEQUENCE {
* name-type[0] INTEGER,
* name-string[1] SEQUENCE OF UTF8String
* }
*
* @author thomask
* @version $Revision$, $Date$
*/
public class KerberosName {
public static final int OID[] = { 1, 3, 6, 1, 5, 2, 2 };
public static final ObjectIdentifier KRB5_PRINCIPAL_NAME = new
ObjectIdentifier(OID);
private String m_realm = null;
private int m_name_type = 0;
private Vector m_name_strings = null;
public KerberosName(String realm, int name_type, Vector name_strings) {
m_realm = realm;
m_name_type = name_type;
m_name_strings = name_strings;
}
/**
* Write the extension to the DerOutputStream.
*
* @param out the DerOutputStream to write the extension to.
* @exception IOException on encoding errors.
*/
public void encode(OutputStream out) throws IOException {
try (DerOutputStream seq = new DerOutputStream()) {
DerOutputStream tmp = new DerOutputStream();
DerOutputStream realm = new DerOutputStream();
realm.putGeneralString(m_realm);
tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0), realm);
DerOutputStream seq1 = new DerOutputStream();
DerOutputStream tmp1 = new DerOutputStream();
DerOutputStream name_type = new DerOutputStream();
name_type.putInteger(new BigInt(m_name_type));
tmp1.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0), name_type);
DerOutputStream name_strings = new DerOutputStream();
DerOutputStream name_string = new DerOutputStream();
for (int i = 0; i < m_name_strings.size(); i++) {
name_string.putGeneralString(m_name_strings.elementAt(i));
}
name_strings.write(DerValue.tag_SequenceOf, name_string);
tmp1.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 1), name_strings);
seq1.write(DerValue.tag_Sequence, tmp1);
tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 1), seq1);
seq.write(DerValue.tag_Sequence, tmp);
out.write(seq.toByteArray());
}
}
public byte[] toByteArray() throws IOException {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
encode(bos);
return bos.toByteArray();
}
@Override
public String toString() {
String strings = null;
for (int i = 0; i < m_name_strings.size(); i++) {
if (strings == null) {
strings = m_name_strings.elementAt(i);
} else {
strings += ",";
strings += m_name_strings.elementAt(i);
}
}
return "Realm: " + m_realm + " Name Type: " + m_name_type + " Name String(s):" + strings;
}
public static void main(String[] argv) {
Vector strings = new Vector<>();
strings.addElement("name");
KerberosName k = new KerberosName("realm", 0, strings);
System.out.println(k.toString());
try {
FileOutputStream os = new FileOutputStream("/tmp/out.der");
k.encode(os);
os.close();
} catch (Exception e) {
System.out.println(e.toString());
}
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/extensions/NSCertTypeExtension.java 0000664 0000000 0000000 00000026474 14565430767 0033371 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.extensions;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.cert.CertificateException;
import java.util.Enumeration;
import java.util.Vector;
import org.mozilla.jss.netscape.security.util.BitArray;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
import org.mozilla.jss.netscape.security.util.ObjectIdentifier;
import org.mozilla.jss.netscape.security.x509.CertAttrSet;
import org.mozilla.jss.netscape.security.x509.Extension;
/**
* NSCertTypeExtension
* Represents Netscape Certificate Type Extension
*
*
* This deprecated extension, if present, defines both the purpose (e.g., encipherment, signature, certificate signing)
* and the application (e.g., SSL, S/Mime or Object Signing of the key contained in the certificate.
*
* @author galperin
* @version $Revision$, $Date$
*/
public class NSCertTypeExtension extends Extension implements CertAttrSet {
/**
*
*/
private static final long serialVersionUID = 1856407688086284397L;
// The object identifiers
private static final int CertType_data[] = { 2, 16, 840, 1, 113730, 1, 1 };
/**
* Identifies the particular public key used to sign the certificate.
*/
public static final ObjectIdentifier CertType_Id = new
ObjectIdentifier(CertType_data);
/**
* Attribute names.
*/
public static final String NAME = "NSCertType";
public static final String SSL_CLIENT = "ssl_client";
public static final String SSL_SERVER = "ssl_server";
public static final String EMAIL = "email";
public static final String OBJECT_SIGNING = "object_signing";
public static final String SSL_CA = "ssl_ca";
public static final String EMAIL_CA = "email_ca";
public static final String OBJECT_SIGNING_CA = "object_signing_ca";
/**
* Attribute names.
*/
public static final int SSL_CLIENT_BIT = 0;
public static final int SSL_SERVER_BIT = 1;
public static final int EMAIL_BIT = 2;
public static final int OBJECT_SIGNING_BIT = 3;
// 4 is reserved.
public static final int SSL_CA_BIT = 5;
public static final int EMAIL_CA_BIT = 6;
public static final int OBJECT_SIGNING_CA_BIT = 7;
public static final int NBITS = 8;
/**
* Identifier for this attribute, to be used with the
* get, set, delete methods of Certificate, x509 type.
*/
public static final String IDENT = "x509.info.extensions.NSCertType";
// Private data members
private byte[] mBitString;
private static class MapEntry {
String mName;
int mPosition;
MapEntry(String name, int position) {
mName = name;
mPosition = position;
}
}
private static MapEntry[] mMapData =
{
new MapEntry(SSL_CLIENT, 0),
new MapEntry(SSL_SERVER, 1),
new MapEntry(EMAIL, 2),
new MapEntry(OBJECT_SIGNING, 3),
// note that bit 4 is reserved
new MapEntry(SSL_CA, 5),
new MapEntry(EMAIL_CA, 6),
new MapEntry(OBJECT_SIGNING_CA, 7),
};
private static Vector mAttributeNames = new Vector<>();
static {
for (int i = 0; i < mMapData.length; ++i) {
mAttributeNames.addElement(mMapData[i].mName);
}
}
private static int getPosition(String name) throws CertificateException {
for (int i = 0; i < mMapData.length; ++i) {
if (name.equalsIgnoreCase(mMapData[i].mName))
return mMapData[i].mPosition;
}
throw new CertificateException("Attribute name [" + name
+ "] not recognized by"
+ " CertAttrSet:NSCertType.");
}
// Encode this extension value
private void encodeThis() throws IOException {
try (DerOutputStream os = new DerOutputStream()) {
os.putUnalignedBitString(mBitString);
this.extensionValue = os.toByteArray();
}
}
/**
* Check if bit is set.
*
* @param position the position in the bit string to check.
*/
public boolean isSet(int position) {
int index = position / 8;
byte pos = (byte) (1 << (7 - (position % 8)));
if (mBitString.length <= index)
return false;
return ((mBitString[index] & pos) != 0);
}
/**
* Set the bit at the specified position.
*/
public void set(int position, boolean val) {
int index = position / 8;
byte pos = (byte) (1 << (7 - (position % 8)));
if (index >= mBitString.length) {
byte[] tmp = new byte[index + 1];
System.arraycopy(mBitString, 0, tmp, 0, mBitString.length);
mBitString = tmp;
}
if (val) {
mBitString[index] |= pos;
} else {
mBitString[index] &= ~pos;
}
}
/**
* Create NSCertTypeExtension from boolean array.
* The criticality is set to false.
*/
public NSCertTypeExtension(boolean critical, boolean[] bits) {
this.extensionId = CertType_Id;
this.critical = critical;
this.mBitString = new byte[0];
for (int i = 0; i < bits.length && i < 8; i++) {
set(i, bits[i]);
}
}
public NSCertTypeExtension(boolean[] bits) {
this.extensionId = CertType_Id;
this.critical = false;
this.mBitString = new byte[0];
for (int i = 0; i < bits.length && i < 8; i++) {
set(i, bits[i]);
}
}
/**
* Create a NSCertTypeExtension with the passed bit settings.
* The criticality is set to false.
*
* @param bitString the bits to be set for the extension.
*/
public NSCertTypeExtension(boolean critical, byte[] bitString) throws IOException {
this.mBitString = bitString;
this.extensionId = CertType_Id;
this.critical = critical;
encodeThis();
}
public NSCertTypeExtension(byte[] bitString) throws IOException {
this.mBitString = bitString;
this.extensionId = CertType_Id;
this.critical = false;
encodeThis();
}
/**
* Create the extension from the passed DER encoded value of the same.
*
* @param critical true if the extension is to be treated as critical.
* @param value Array of DER encoded bytes of the actual value.
* @exception IOException on error.
*/
public NSCertTypeExtension(Boolean critical, Object value)
throws IOException {
/**
* logger.trace("NSCertTypeExtension");
* this.mBitString = new byte[1];
* this.mBitString[0] = (byte)0x00;
* return;
**/
this.extensionId = CertType_Id;
this.critical = critical.booleanValue();
byte[] extValue = ((byte[]) value).clone();
this.extensionValue = extValue;
DerValue val = new DerValue(extValue);
BitArray bitArray = val.getUnalignedBitString();
if (bitArray == null) {
throw new IOException("Invalid Encoded DER Value");
}
this.mBitString = bitArray.toByteArray();
}
/**
* Create a default key usage.
*/
public NSCertTypeExtension() {
this.extensionId = CertType_Id;
this.critical = false;
this.mBitString = new byte[0];
try {
encodeThis();
} catch (Exception e) {
}
}
/**
* Set the attribute value.
*/
@Override
public void set(String name, Object obj) throws CertificateException {
if (!(obj instanceof Boolean)) {
throw new CertificateException("Attribute must be of type Boolean.");
}
boolean val = ((Boolean) obj).booleanValue();
set(getPosition(name), val);
}
/**
* Get the attribute value.
*/
@Override
public Object get(String name) throws CertificateException {
return Boolean.valueOf(isSet(getPosition(name)));
}
/**
* Delete the attribute value.
*/
@Override
public void delete(String name) throws CertificateException {
set(getPosition(name), false);
}
/**
* Returns a printable representation of the NSCertType.
*/
@Override
public String toString() {
String s = super.toString() + "NSCertType [\n";
try {
if (isSet(getPosition(SSL_CLIENT))) {
s += " SSL client";
}
if (isSet(getPosition(SSL_SERVER))) {
s += " SSL server";
}
if (isSet(getPosition(EMAIL))) {
s += " Email";
}
if (isSet(getPosition(OBJECT_SIGNING))) {
s += " Object Signing";
}
if (isSet(getPosition(SSL_CA))) {
s += " SSL CA";
}
if (isSet(getPosition(EMAIL_CA))) {
s += " Email CA";
}
if (isSet(getPosition(OBJECT_SIGNING_CA))) {
s += " Object Signing CA";
}
} catch (Exception e) {
// this is reached only if there is a bug
throw new IllegalArgumentException(e.getMessage());
}
s += "]\n";
return (s);
}
/**
* Decode the extension from the InputStream.
*
* @param in the InputStream to unmarshal the contents from.
* @exception IOException on decoding or validity errors.
*/
@Override
public void decode(InputStream in) throws IOException {
throw new IOException("Method not to be called directly.");
}
/**
* Write the extension to the DerOutputStream.
*
* @param out the DerOutputStream to write the extension to.
* @exception IOException on encoding errors.
*/
@Override
public void encode(OutputStream out) throws IOException {
DerOutputStream tmp = new DerOutputStream();
encodeThis();
if (this.extensionValue == null) {
this.extensionId = CertType_Id;
this.critical = true;
}
super.encode(tmp);
out.write(tmp.toByteArray());
}
/**
* Return an enumeration of names of attributes existing within this
* attribute.
*/
@Override
public Enumeration getAttributeNames() {
return mAttributeNames.elements();
}
/**
* Return the name of this attribute.
*/
@Override
public String getName() {
return (NAME);
}
public static void main(String[] argv) {
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/extensions/OCSPNoCheckExtension.java 0000664 0000000 0000000 00000011167 14565430767 0033361 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.extensions;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.cert.CertificateException;
import java.util.Enumeration;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.ObjectIdentifier;
import org.mozilla.jss.netscape.security.x509.CertAttrSet;
import org.mozilla.jss.netscape.security.x509.Extension;
import org.mozilla.jss.netscape.security.x509.OIDMap;
/**
* This represents the OCSPNoCheck extension.
*/
public class OCSPNoCheckExtension extends Extension implements CertAttrSet {
/**
*
*/
private static final long serialVersionUID = -4692759557964594790L;
public static final String OID = "1.3.6.1.5.5.7.48.1.5";
public static final String NAME = "OCSPNoCheckExtension";
private byte mCached[] = null;
static {
try {
OIDMap.addAttribute(OCSPNoCheckExtension.class.getName(),
OID, NAME);
} catch (CertificateException e) {
}
}
public OCSPNoCheckExtension() throws IOException {
this(Boolean.FALSE);
}
public OCSPNoCheckExtension(Boolean crit) throws IOException {
try {
extensionId = ObjectIdentifier.getObjectIdentifier(OCSPNoCheckExtension.OID);
} catch (IOException e) {
// never here
}
critical = crit.booleanValue();
DerOutputStream tmpD = new DerOutputStream();
try {
tmpD.putNull();
} catch (IOException ex) {
} finally {
tmpD.close();
}
extensionValue = tmpD.toByteArray();
}
public OCSPNoCheckExtension(Boolean crit, Object byteVal) {
try {
extensionId = ObjectIdentifier.getObjectIdentifier(OCSPNoCheckExtension.OID);
} catch (IOException e) {
// never here
}
critical = crit.booleanValue();
extensionValue = ((byte[]) byteVal).clone();
}
@Override
public void setCritical(boolean newValue) {
if (critical != newValue) {
critical = newValue;
mCached = null;
}
}
@Override
public void encode(DerOutputStream out) throws IOException {
if (mCached == null) {
super.encode(out);
mCached = out.toByteArray();
}
}
@Override
public String toString() {
String presentation = "oid=" + OID + " ";
if (critical) {
presentation += "critical=true";
}
if (extensionValue != null) {
StringBuffer extByteValue = new StringBuffer(" val=");
for (int i = 0; i < extensionValue.length; i++) {
extByteValue.append(extensionValue[i] + " ");
}
presentation += extByteValue.toString();
}
return presentation;
}
@Override
public void decode(InputStream in)
throws CertificateException, IOException {
// NOT USED
}
@Override
public void encode(OutputStream out)
throws CertificateException, IOException {
if (mCached == null) {
DerOutputStream temp = new DerOutputStream();
encode(temp);
}
out.write(mCached);
}
@Override
public void set(String name, Object obj)
throws CertificateException, IOException {
// NOT USED
}
@Override
public Object get(String name) throws CertificateException, IOException {
// NOT USED
return null;
}
@Override
public Enumeration getAttributeNames() {
// NOT USED
return null;
}
@Override
public String getName() {
return NAME;
}
@Override
public void delete(String name)
throws CertificateException, IOException {
// NOT USED
}
}
PresenceServerExtension.java 0000664 0000000 0000000 00000024635 14565430767 0034242 0 ustar 00root root 0000000 0000000 jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/extensions // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.extensions;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.cert.CertificateException;
import java.util.Enumeration;
import org.mozilla.jss.netscape.security.util.BigInt;
import org.mozilla.jss.netscape.security.util.DerInputStream;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
import org.mozilla.jss.netscape.security.util.ObjectIdentifier;
import org.mozilla.jss.netscape.security.x509.CertAttrSet;
import org.mozilla.jss.netscape.security.x509.Extension;
public class PresenceServerExtension extends Extension implements CertAttrSet {
/**
*
*/
private static final long serialVersionUID = -6333109673043357921L;
private boolean mCritical;
private int mVersion = 0;
private String mStreetAddress = null;
private String mTelephoneNumber = null;
private String mRFC822Name = null;
private String mID = null;
private String mHostName = null;
private int mPortNumber = 0;
private int mMaxUsers = 0;
private int mServiceLevel = 0;
public static final String OID = "2.16.840.1.113730.1.18";
/*
public PresenceServerExtension()
{
}
*/
public PresenceServerExtension(Boolean critical, Object value)
throws IOException {
this.extensionId = new ObjectIdentifier(OID);
this.critical = critical.booleanValue();
this.extensionValue = ((byte[]) value).clone();
decodeThis();
}
public PresenceServerExtension(
boolean critical,
int version,
String streetAddress,
String telephoneNumber,
String rfc822Name,
String ID,
String hostName,
int portNumber,
int maxUsers,
int serviceLevel)
throws IOException {
mCritical = critical;
mVersion = version;
mStreetAddress = streetAddress;
mTelephoneNumber = telephoneNumber;
mRFC822Name = rfc822Name;
mID = ID;
mHostName = hostName;
mPortNumber = portNumber;
mMaxUsers = maxUsers;
mServiceLevel = serviceLevel;
this.extensionId = new ObjectIdentifier(OID);
this.critical = mCritical;
encodeThis();
}
public int getVersion() {
return mVersion;
}
public String getStreetAddress() {
return mStreetAddress;
}
public String getTelephoneNumber() {
return mTelephoneNumber;
}
public String getRFC822() {
return mRFC822Name;
}
public String getID() {
return mID;
}
public String getHostName() {
return mHostName;
}
public int getPortNumber() {
return mPortNumber;
}
public int getMaxUsers() {
return mMaxUsers;
}
public int getServiceLevel() {
return mServiceLevel;
}
public void encodeThis() throws IOException {
try (DerOutputStream out = new DerOutputStream()) {
DerOutputStream temp = new DerOutputStream();
temp.putInteger(new BigInt(mVersion));
temp.putOctetString(mStreetAddress.getBytes());
temp.putOctetString(mTelephoneNumber.getBytes());
temp.putOctetString(mRFC822Name.getBytes());
temp.putOctetString(mID.getBytes());
temp.putOctetString(mHostName.getBytes());
temp.putInteger(new BigInt(mPortNumber));
temp.putInteger(new BigInt(mMaxUsers));
temp.putInteger(new BigInt(mServiceLevel));
out.write(DerValue.tag_Sequence, temp);
this.extensionValue = out.toByteArray();
}
}
public void decodeThis() throws IOException {
DerInputStream val = new DerInputStream(this.extensionValue);
byte data[] = null;
DerValue seq[] = val.getSequence(0);
mVersion = seq[0].getInteger().toInt();
data = null;
if (seq[1].length() > 0) {
data = seq[1].getOctetString();
}
if (data == null) {
mStreetAddress = "";
} else {
mStreetAddress = new String(data);
}
data = null;
if (seq[2].length() > 0)
data = seq[2].getOctetString();
if (data == null) {
mTelephoneNumber = "";
} else {
mTelephoneNumber = new String(data);
}
data = null;
if (seq[3].length() > 0)
data = seq[3].getOctetString();
if (data == null) {
mRFC822Name = "";
} else {
mRFC822Name = new String(data);
}
data = null;
if (seq[4].length() > 0)
data = seq[4].getOctetString();
if (data == null) {
mID = "";
} else {
mID = new String(data);
}
data = null;
if (seq[5].length() > 0)
data = seq[5].getOctetString();
if (data == null) {
mHostName = "";
} else {
mHostName = new String(data);
}
mPortNumber = seq[6].getInteger().toInt();
mMaxUsers = seq[7].getInteger().toInt();
mServiceLevel = seq[8].getInteger().toInt();
}
@Override
public void decode(InputStream in)
throws CertificateException, IOException {
}
@Override
public void encode(OutputStream out)
throws CertificateException, IOException {
DerOutputStream dos = new DerOutputStream();
super.encode(dos);
out.write(dos.toByteArray());
}
/**
* Set the attribute value.
*/
@Override
public void set(String name, Object obj) throws IOException {
throw new IOException("Method not to be called directly.");
}
/**
* Get the attribute value.
*/
@Override
public Object get(String name) throws IOException {
return null;
}
/**
* Delete the attribute value.
*/
@Override
public void delete(String name) throws IOException {
throw new IOException("Method not to be called directly.");
}
@Override
public Enumeration getAttributeNames() {
return null;
}
/**
* Return the name of this attribute.
*/
@Override
public String getName() {
return "PresenceServerExtension";
}
/**
* Set the name of this attribute.
*/
public void setName(String name) {
}
/**
* Return the OID of this attribute.
*/
public String getOID() {
return OID;
}
/**
* Set the OID of this attribute.
*/
public void setOID(String oid) {
}
public static void main(String args[]) {
/*
0 30 115: SEQUENCE {
2 06 9: OBJECT IDENTIFIER '2 16 840 1 113730 1 100'
13 04 102: OCTET STRING, encapsulates {
15 30 100: SEQUENCE {
17 02 1: INTEGER 0
20 04 31: OCTET STRING
: 34 30 31 45 20 4D 69 64 64 6C 65 66 69 65 6C 64
: 20 52 64 2E 2C 4D 56 2C 43 41 39 34 30 34 31
53 04 12: OCTET STRING
: 36 35 30 2D 31 31 31 2D 31 31 31 31
67 04 18: OCTET STRING
: 61 64 6D 69 6E 40 6E 65 74 73 63 61 70 65 2E 63
: 6F 6D
87 04 10: OCTET STRING
: 70 73 2D 63 61 70 69 74 6F 6C
99 04 7: OCTET STRING
: 63 61 70 69 74 6F 6C
108 02 1: INTEGER 80
111 02 1: INTEGER 10
114 02 1: INTEGER 1
: }
: }
: }
*/
ByteArrayOutputStream dos = null;
FileOutputStream fos = null;
try {
boolean critical = false;
int version = 1;
String streetAddress = "401E Middlefield Rd.,MV,CA94041";
String telephoneNumber = "650-111-1111";
String rfc822Name = "admin@netscape.com";
String ID = "ps-capitol";
String hostName = "capitol";
int portNumber = 80;
int maxUsers = 10;
int serviceLevel = 1;
PresenceServerExtension ext = new PresenceServerExtension(
critical,
version, streetAddress, telephoneNumber,
rfc822Name, ID, hostName, portNumber,
maxUsers, serviceLevel);
// encode
dos = new ByteArrayOutputStream();
ext.encode(dos);
fos = new FileOutputStream("pse.der");
fos.write(dos.toByteArray());
Extension ext1 = new Extension(new DerValue(dos.toByteArray()));
@SuppressWarnings("unused")
PresenceServerExtension ext2 = new PresenceServerExtension(
Boolean.valueOf(false), ext1.getExtensionValue());
} catch (IOException e) {
e.printStackTrace();
} catch (CertificateException e) {
e.printStackTrace();
} finally {
if (dos != null) {
try {
dos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (fos != null) {
try {
fos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
SubjectInfoAccessExtension.java 0000664 0000000 0000000 00000020527 14565430767 0034640 0 ustar 00root root 0000000 0000000 jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/extensions // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.extensions;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.security.cert.CertificateException;
import java.util.Enumeration;
import java.util.Vector;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
import org.mozilla.jss.netscape.security.util.ObjectIdentifier;
import org.mozilla.jss.netscape.security.util.Utils;
import org.mozilla.jss.netscape.security.x509.CertAttrSet;
import org.mozilla.jss.netscape.security.x509.Extension;
import org.mozilla.jss.netscape.security.x509.GeneralName;
import org.mozilla.jss.netscape.security.x509.URIName;
/**
* This represents the subject information access extension
* as defined in RFC3280.
*
* @author thomask
* @version $Revision$, $Date$
*/
public class SubjectInfoAccessExtension extends Extension implements CertAttrSet {
private static final long serialVersionUID = 7237321566602583325L;
public static final String NAME = "SubjectInfoAccessExtension";
public static final int OID_OCSP[] = { 1, 3, 6, 1, 5, 5, 7, 48, 1 };
public static final ObjectIdentifier METHOD_OCSP = new
ObjectIdentifier(OID_OCSP);
public static final int OID_CA_ISSUERS[] = { 1, 3, 6, 1, 5, 5, 7, 48, 2 };
public static final ObjectIdentifier METHOD_CA_ISSUERS = new
ObjectIdentifier(OID_CA_ISSUERS);
public static final int OID[] = { 1, 3, 6, 1, 5, 5, 7, 1, 11 };
public static final ObjectIdentifier ID = new ObjectIdentifier(OID);
private Vector mDesc = new Vector<>();
/**
* Create the extension from the passed DER encoded value of the same.
*
* @param critical true if the extension is to be treated as critical.
*/
public SubjectInfoAccessExtension(boolean critical) {
this.extensionId = ID;
this.critical = critical;
this.extensionValue = null; // build this when encodeThis() is called
}
/**
* Create the extension from the passed DER encoded value of the same.
*
* @param critical true if the extension is to be treated as critical.
* @param value Array of DER encoded bytes of the actual value.
* @exception IOException on error.
*/
public SubjectInfoAccessExtension(Boolean critical, Object value)
throws IOException {
this.extensionId = ID;
this.critical = critical.booleanValue();
this.extensionValue = ((byte[]) value).clone();
decodeThis();
}
/**
* Sets extension attribute.
*/
@Override
public void set(String name, Object obj) throws CertificateException {
// NOT USED
}
/**
* Retrieves extension attribute.
*/
@Override
public Object get(String name) throws CertificateException {
// NOT USED
return null;
}
/**
* Deletes attribute.
*/
@Override
public void delete(String name) throws CertificateException {
// NOT USED
}
/**
* Decodes this extension.
*/
@Override
public void decode(InputStream in) throws IOException {
// NOT USED
}
/**
* Return an enumeration of names of attributes existing within this
* attribute.
*/
@Override
public Enumeration getAttributeNames() {
// NOT USED
return null;
}
/**
* Return the name of this attribute.
*/
@Override
public String getName() {
return NAME;
}
/**
* Adds Access Description.
*/
public void addAccessDescription(
ObjectIdentifier method,
GeneralName gn) {
clearValue();
mDesc.addElement(new AccessDescription(method, gn));
}
public AccessDescription getAccessDescription(int pos) {
return mDesc.elementAt(pos);
}
/**
* Returns the number of access description.
*/
public int numberOfAccessDescription() {
return mDesc.size();
}
private void decodeThis() throws IOException {
DerValue val = new DerValue(this.extensionValue);
if (val.tag != DerValue.tag_Sequence) {
throw new IOException("Invalid encoding of AuthInfoAccess extension");
}
while (val.data.available() != 0) {
DerValue seq = val.data.getDerValue();
ObjectIdentifier method = seq.data.getDerValue().getOID();
GeneralName gn = new GeneralName(seq.data.getDerValue());
addAccessDescription(method, gn);
}
}
private void encodeThis() throws IOException {
try (DerOutputStream seq = new DerOutputStream();
DerOutputStream tmp = new DerOutputStream()) {
for (int i = 0; i < mDesc.size(); i++) {
DerOutputStream tmp0 = new DerOutputStream();
AccessDescription ad = mDesc.elementAt(i);
tmp0.putOID(ad.getMethod());
ad.getLocation().encode(tmp0);
tmp.write(DerValue.tag_Sequence, tmp0);
}
seq.write(DerValue.tag_Sequence, tmp);
this.extensionValue = seq.toByteArray();
}
}
/**
* Write the extension to the DerOutputStream.
*
* @param out the DerOutputStream to write the extension to.
* @exception IOException on encoding errors.
*/
@Override
public void encode(OutputStream out) throws IOException {
DerOutputStream tmp = new DerOutputStream();
if (this.extensionValue == null) {
encodeThis();
}
super.encode(tmp);
out.write(tmp.toByteArray());
}
/**
* Returns a printable representation of the AuthInfoAccess.
*/
@Override
public String toString() {
StringBuffer s=new StringBuffer(super.toString() + "AuthInfoAccess [\n");
for (int i = 0; i < mDesc.size(); i++) {
AccessDescription ad = mDesc.elementAt(i);
s.append( "(" + i + ")");
s.append(" ");
s.append(ad.getMethod().toString() + " " + ad.getLocation().toString());
}
return (s.toString() + "]\n");
}
public static void main(String[] argv) {
AuthInfoAccessExtension aia = new AuthInfoAccessExtension(false);
GeneralName ocspName = new GeneralName(new
URIName("http://ocsp.netscape.com"));
aia.addAccessDescription(METHOD_OCSP, ocspName);
GeneralName caIssuersName = new GeneralName(new
URIName("http://ocsp.netscape.com"));
aia.addAccessDescription(METHOD_CA_ISSUERS, caIssuersName);
ByteArrayOutputStream os = new ByteArrayOutputStream();
try {
aia.encode(os);
System.out.println(Utils.base64encode(os.toByteArray(), true));
} catch (IOException e) {
System.out.println(e.toString());
}
try {
// test serialization
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(bos);
oos.writeObject(aia);
ByteArrayInputStream bis = new ByteArrayInputStream(
bos.toByteArray());
ObjectInputStream ois = new ObjectInputStream(bis);
AuthInfoAccessExtension clone = (AuthInfoAccessExtension)
ois.readObject();
System.out.println(clone);
} catch (Exception e) {
System.out.println(e.toString());
}
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/pkcs/ 0000775 0000000 0000000 00000000000 14565430767 0025355 5 ustar 00root root 0000000 0000000 jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/pkcs/ContentInfo.java 0000664 0000000 0000000 00000012676 14565430767 0030462 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.pkcs;
import java.io.IOException;
import org.mozilla.jss.netscape.security.util.DerInputStream;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
import org.mozilla.jss.netscape.security.util.ObjectIdentifier;
/**
* A ContentInfo type, as defined in PKCS#7.
*
* @version 1.12
* @author Benjamin Renaud
*/
public class ContentInfo {
// pkcs7 pre-defined content types
private static int[] pkcs7 = { 1, 2, 840, 113549, 1, 7 };
private static int[] data = { 1, 2, 840, 113549, 1, 7, 1 };
private static int[] sdata = { 1, 2, 840, 113549, 1, 7, 2 };
private static int[] edata = { 1, 2, 840, 113549, 1, 7, 3 };
private static int[] sedata = { 1, 2, 840, 113549, 1, 7, 4 };
private static int[] ddata = { 1, 2, 840, 113549, 1, 7, 5 };
private static int[] crdata = { 1, 2, 840, 113549, 1, 7, 6 };
public static final ObjectIdentifier PKCS7_OID =
new ObjectIdentifier(pkcs7);
public static final ObjectIdentifier DATA_OID =
new ObjectIdentifier(data);
public static final ObjectIdentifier SIGNED_DATA_OID =
new ObjectIdentifier(sdata);
public static final ObjectIdentifier ENVELOPED_DATA_OID =
new ObjectIdentifier(edata);
public static final ObjectIdentifier SIGNED_AND_ENVELOPED_DATA_OID =
new ObjectIdentifier(sedata);
public static final ObjectIdentifier DIGESTED_DATA_OID =
new ObjectIdentifier(ddata);
public static final ObjectIdentifier ENCRYPTED_DATA_OID =
new ObjectIdentifier(crdata);
ObjectIdentifier contentType;
DerValue content; // OPTIONAL
public ContentInfo(ObjectIdentifier contentType, DerValue content) {
this.contentType = contentType;
this.content = content;
}
/**
* Make a contentInfo of type data.
*/
public ContentInfo(byte[] bytes) {
this.contentType = DATA_OID;
if (bytes!=null && bytes.length > 0) {
DerValue octetString = new DerValue(DerValue.tag_OctetString, bytes);
this.content = octetString;
}
}
public ContentInfo(DerInputStream derin)
throws IOException, ParsingException {
DerInputStream disType;
DerInputStream disTaggedContent;
DerValue type;
DerValue taggedContent;
DerValue[] typeAndContent;
DerValue[] contents;
typeAndContent = derin.getSequence(2);
// Parse the content type
type = typeAndContent[0];
disType = new DerInputStream(type.toByteArray());
contentType = disType.getOID();
// Parse the content (OPTIONAL field).
// Skip the [0] EXPLICIT tag by pretending that the content is the one
// and only element in an implicitly tagged set
if (typeAndContent.length > 1) { // content is OPTIONAL
taggedContent = typeAndContent[1];
disTaggedContent = new DerInputStream(taggedContent.toByteArray());
contents = disTaggedContent.getSet(1, true);
content = contents[0];
}
}
public DerValue getContent() {
return content;
}
public byte[] getData() throws IOException {
if (contentType.equals(DATA_OID)) {
return content!= null ? content.getOctetString() : new byte[0];
}
throw new IOException("content type is not DATA: " + contentType);
}
public void encode(DerOutputStream out) throws IOException {
DerOutputStream contentDerCode;
DerOutputStream seq;
DerValue taggedContent;
seq = new DerOutputStream();
seq.putOID(contentType);
if( content!=null) {
contentDerCode = new DerOutputStream();
content.encode(contentDerCode);
// Add the [0] EXPLICIT tag in front of the content encoding
taggedContent = new DerValue((byte) 0xA0,
contentDerCode.toByteArray());
seq.putDerValue(taggedContent);
}
out.write(DerValue.tag_Sequence, seq);
}
/**
* Returns a byte array representation of the data held in
* the content field.
*/
public byte[] getContentBytes() throws IOException {
if(content == null) {
return new byte[0];
}
DerInputStream dis = new DerInputStream(content.toByteArray());
return dis.getOctetString();
}
@Override
public String toString() {
String out = "";
out += "Content Info Sequence\n\tContent type: " + contentType + "\n";
if (content != null) {
out += "\tContent: " + content;
}
return out;
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/pkcs/EncodingException.java 0000664 0000000 0000000 00000002565 14565430767 0031635 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.pkcs;
public class EncodingException extends Exception {
/**
*
*/
private static final long serialVersionUID = -6126764125859196917L;
public EncodingException() {
super();
}
public EncodingException(String mesg) {
super(mesg);
}
public EncodingException(String mesg, Throwable cause) {
super(mesg, cause);
}
public EncodingException(String mesg, Throwable cause, boolean enableSuppression, boolean writableStackTrace) {
super(mesg, cause, enableSuppression, writableStackTrace);
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/pkcs/PKCS10.java 0000664 0000000 0000000 00000032124 14565430767 0027123 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.pkcs;
import java.io.IOException;
import java.io.PrintStream;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.cert.CertificateException;
import org.mozilla.jss.netscape.security.util.BigInt;
import org.mozilla.jss.netscape.security.util.Cert;
import org.mozilla.jss.netscape.security.util.DerInputStream;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
import org.mozilla.jss.netscape.security.util.Utils;
import org.mozilla.jss.netscape.security.x509.AlgorithmId;
import org.mozilla.jss.netscape.security.x509.X500Name;
import org.mozilla.jss.netscape.security.x509.X500Signer;
import org.mozilla.jss.netscape.security.x509.X509Key;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* PKCS #10 certificate requests are created and sent to Certificate
* Authorities, which then create X.509 certificates and return them to
* the entity which created the certificate request. These cert requests
* basically consist of the subject's X.500 name and public key, signed
* using the corresponding private key.
*
* The ASN.1 syntax for a Certification Request is:
*
*
* CertificationRequest ::= SEQUENCE {
* certificationRequestInfo CertificationRequestInfo,
* signatureAlgorithm SignatureAlgorithmIdentifier,
* signature Signature
* }
*
* SignatureAlgorithmIdentifier ::= AlgorithmIdentifier
* Signature ::= BIT STRING
*
* CertificationRequestInfo ::= SEQUENCE {
* version Version,
* subject Name,
* subjectPublicKeyInfo SubjectPublicKeyInfo,
* attributes [0] IMPLICIT Attributes
* }
* Attributes ::= SET OF Attribute
*
*
* @author David Brownell
* @author Amit Kapoor
* @author Hemma Prafullchandra
* @version 1.28
*/
public class PKCS10 {
public static Logger logger = LoggerFactory.getLogger(PKCS10.class);
/**
* Constructs an unsigned PKCS #10 certificate request. Before this
* request may be used, it must be encoded and signed. Then it
* must be retrieved in some conventional format (e.g. string).
*
* @param publicKey the public key that should be placed
* into the certificate generated by the CA.
*/
public PKCS10(X509Key publicKey) {
subjectPublicKeyInfo = publicKey;
attributeSet = new PKCS10Attributes();
}
/**
* Constructs an unsigned PKCS #10 certificate request. Before this
* request may be used, it must be encoded and signed. Then it
* must be retrieved in some conventional format (e.g. string).
*
* @param publicKey the public key that should be placed
* into the certificate generated by the CA.
* @param attributes additonal set of PKCS10 attributes requested
* for in the certificate.
*/
public PKCS10(X509Key publicKey, PKCS10Attributes attributes) {
subjectPublicKeyInfo = publicKey;
if (attributes != null)
attributeSet = attributes;
else
attributeSet = new PKCS10Attributes();
}
/**
* Parses an encoded, signed PKCS #10 certificate request, verifying
* the request's signature as it does so. This constructor would
* typically be used by a Certificate Authority, from which a new
* certificate would then be constructed.
*
* @param data the DER-encoded PKCS #10 request.
* @param sigver boolean specifies signature verification enabled or not
* @exception IOException for low level errors reading the data
* @exception SignatureException when the signature is invalid
* @exception NoSuchAlgorithmException when the signature
* algorithm is not supported in this environment
*/
public PKCS10(byte data[], boolean sigver)
throws IOException, SignatureException, NoSuchAlgorithmException, java.security.NoSuchProviderException {
DerInputStream in;
DerValue seq[];
AlgorithmId id;
byte sigData[];
Signature sig;
String msg = "";
logger.debug("PKCS10: begins");
if (data == null) {
throw new IllegalArgumentException("Missing PKCS #10 data");
}
certificateRequest = data;
//
// Outer sequence: request, signature algorithm, signature.
// Parse, and prepare to verify later.
//
in = new DerInputStream(data);
seq = in.getSequence(3);
if (seq == null) {
throw new IllegalArgumentException("in.getSequence null");
}
if (seq.length != 3) {
throw new IllegalArgumentException("Invalid PKCS #10 request");
}
data = seq[0].toByteArray(); // reusing this variable
certRequestInfo = seq[0].toByteArray(); // make a copy
id = AlgorithmId.parse(seq[1]);
sigData = seq[2].getBitString();
//
// Inner sequence: version, name, key, attributes
//
@SuppressWarnings("unused")
BigInt serial = seq[0].data.getInteger(); // consume serial
/*
if (serial.toInt () != 0)
throw new IllegalArgumentException ("not PKCS #10 v1");
*/
subject = new X500Name(seq[0].data);
msg = "Request Subject: " + subject + ": ";
byte val1[] = seq[0].data.getDerValue().toByteArray();
subjectPublicKeyInfo = X509Key.parse(new DerValue(val1));
PublicKey publicKey = X509Key.parsePublicKey(new DerValue(val1));
if (publicKey == null) {
logger.error("PKCS10: " + msg + "publicKey null");
throw new SignatureException(msg + "publicKey null");
}
// Cope with a somewhat common illegal PKCS #10 format
if (seq[0].data.available() != 0) {
attributeSet = new PKCS10Attributes(seq[0].data);
} else {
attributeSet = new PKCS10Attributes();
}
//
// OK, we parsed it all ... validate the signature using the
// key and signature algorithm we found.
// temporary commented out
try {
String idName = id.getName();
if (idName.equals("MD5withRSA"))
idName = "MD5/RSA";
else if (idName.equals("MD2withRSA"))
idName = "MD2/RSA";
else if (idName.equals("SHA1withRSA"))
idName = "SHA1/RSA";
else if (idName.equals("SHA1withDSA"))
idName = "SHA1/DSA";
else if (idName.equals("SHA256withRSA"))
idName = "SHA256/RSA";
else if (idName.equals("SHA384withRSA"))
idName = "SHA384/RSA";
else if (idName.equals("SHA512withRSA"))
idName = "SHA512/RSA";
else if (idName.equals("SHA1withEC"))
idName = "SHA1/EC";
else if (idName.equals("SHA256withEC"))
idName = "SHA256/EC";
else if (idName.equals("SHA384withEC"))
idName = "SHA384/EC";
else if (idName.equals("SHA512withEC"))
idName = "SHA512/EC";
if (sigver) {
sig = Signature.getInstance(idName, "Mozilla-JSS");
sig.initVerify(publicKey);
sig.update(data);
if (!sig.verify(sigData)) {
logger.error("PKCS10: " + msg + "sig.verify() failed");
throw new SignatureException(msg + "Invalid PKCS #10 signature");
}
}
} catch (InvalidKeyException e) {
logger.error("PKCS10: " + msg + e.getMessage());
throw new SignatureException(msg + "invalid key", e);
}
logger.debug("PKCS10: ends");
}
public PKCS10(byte data[])
throws IOException, SignatureException, NoSuchAlgorithmException, java.security.NoSuchProviderException {
this(data, true);
}
/**
* Create the signed certificate request. This will later be
* retrieved in either string or binary format.
*
* @param requester identifies the signer (by X.500 name)
* and provides the private key used to sign.
* @exception IOException on errors.
* @exception CertificateException on certificate handling errors.
* @exception SignatureException on signature handling errors.
*/
public void encodeAndSign(X500Signer requester)
throws CertificateException, IOException, SignatureException {
DerOutputStream out, scratch;
byte certificateRequestInfo[];
byte sig[];
if (certificateRequest != null)
throw new SignatureException("request is already signed");
subject = requester.getSigner();
/*
* Encode cert request info, wrap in a sequence for signing
*/
scratch = new DerOutputStream();
scratch.putInteger(new BigInt(0)); // version zero
subject.encode(scratch); // X.500 name
subjectPublicKeyInfo.encode(scratch); // public key
attributeSet.encode(scratch);
out = new DerOutputStream();
out.write(DerValue.tag_Sequence, scratch); // wrap it!
certificateRequestInfo = out.toByteArray();
scratch = out;
/*
* Sign it ...
*/
requester.update(certificateRequestInfo, 0,
certificateRequestInfo.length);
sig = requester.sign();
/*
* Build guts of SIGNED macro
*/
requester.getAlgorithmId().encode(scratch); // sig algorithm
scratch.putBitString(sig); // sig
/*
* Wrap those guts in a sequence
*/
out = new DerOutputStream();
out.write(DerValue.tag_Sequence, scratch);
certificateRequest = out.toByteArray();
}
/**
* Returns the subject's name.
*/
public X500Name getSubjectName() {
return subject;
}
/**
* Returns the subject's public key.
*/
public X509Key getSubjectPublicKeyInfo() {
return subjectPublicKeyInfo;
}
/**
* Returns the additional attributes requested.
*/
public PKCS10Attributes getAttributes() {
return attributeSet;
}
/**
* Returns the encoded and signed certificate request as a
* DER-encoded byte array.
*
* @return the certificate request, or null if encodeAndSign()
* has not yet been called.
*/
public byte[] toByteArray() {
return certificateRequest;
}
/**
* Prints an E-Mailable version of the certificate request on the print
* stream passed. The format is a common base64 encoded one, supported
* by most Certificate Authorities because Netscape web servers have
* used this for some time. Some certificate authorities expect some
* more information, in particular contact information for the web
* server administrator.
*
* @param out the print stream where the certificate request
* will be printed.
* @exception IOException when an output operation failed
* @exception SignatureException when the certificate request was
* not yet signed.
*/
public void print(PrintStream out)
throws IOException, SignatureException {
if (certificateRequest == null)
throw new SignatureException("Cert request was not signed");
out.println(Cert.REQUEST_HEADER);
out.print(Utils.base64encode(certificateRequest, true));
out.println(Cert.REQUEST_FOOTER);
}
/**
* Provides a short description of this request.
*/
@Override
public String toString() {
return "[PKCS #10 certificate request:\n"
+ subjectPublicKeyInfo.toString()
+ " subject: <" + subject + ">" + "\n"
+ " attributes: " + attributeSet.toString()
+ "\n]";
}
/**
* Retrieve the PKCS10 CertificateRequestInfo as a byte array
*/
public byte[] getCertRequestInfo() {
return certRequestInfo;
}
private X500Name subject;
private X509Key subjectPublicKeyInfo;
private PKCS10Attributes attributeSet;
private byte certificateRequest[]; // signed
private byte certRequestInfo[]; // inner content signed
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/pkcs/PKCS10Attribute.java 0000664 0000000 0000000 00000020551 14565430767 0031010 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.pkcs;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Serializable;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.security.cert.CertificateException;
import org.mozilla.jss.netscape.security.util.DerEncoder;
import org.mozilla.jss.netscape.security.util.DerInputStream;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
import org.mozilla.jss.netscape.security.util.ObjectIdentifier;
import org.mozilla.jss.netscape.security.x509.ACertAttrSet;
import org.mozilla.jss.netscape.security.x509.CertAttrSet;
import org.mozilla.jss.netscape.security.x509.Extensions;
import org.mozilla.jss.netscape.security.x509.OIDMap;
/**
* Represent a PKCS Attribute.
*
*
* Attributes are addiitonal attributes which can be inserted in a PKCS certificate request. For example a
* "Driving License Certificate" could have the driving license number as a attribute.
*
*
* Attributes are represented as a sequence of the attribute identifier (Object Identifier) and a set of DER encoded
* attribute values. The current implementation only supports one value per attribute.
*
* ASN.1 definition of Attribute:
*
*
* Attribute :: SEQUENCE {
* type AttributeValue,
* values SET OF AttributeValue
* }
* AttributeValue ::= ANY
*
*
* @author Amit Kapoor
* @author Hemma Prafullchandra
* @version 1.13
*/
public class PKCS10Attribute implements DerEncoder, Serializable {
private static final long serialVersionUID = 2002480042340316170L;
protected ObjectIdentifier attributeId = null;
protected CertAttrSet attributeValue = null;
/**
* Default constructor. Used only by sub-classes.
*/
public PKCS10Attribute() {
}
/**
* Constructs an attribute from a DER encoded array of bytes.
*/
public PKCS10Attribute(DerValue derVal) throws IOException {
if (derVal.tag != DerValue.tag_Sequence) {
throw new IOException("Sequence tag missing for PKCS10Attribute.");
}
DerInputStream in = derVal.toDerInputStream();
// Object identifier
attributeId = in.getOID();
// System.out.println("attribute ID in pkcs10 "+attributeId.toString());
// Rest of the stuff is attribute value(s), wrapped in a SET.
// For now, assume there is only one attribute value present.
DerValue[] inAttrValues = in.getSet(1);
int attrValueNum = inAttrValues.length;
if (attrValueNum > 1) {
throw new IOException("More than one value per attribute not supported");
}
// Read the first attribute value
DerValue inAttrValue = inAttrValues[0];
if (attributeId.equals(PKCS9Attribute.EXTENSION_REQUEST_OID)) {
//pkcs9 extensionAttr
try {
// remove the tag
//DerValue dv = inAttrValue.data.getDerValue();
// hack. toDerInputStream only gives one extension.
DerInputStream fi = new DerInputStream(inAttrValue.toByteArray());
attributeValue = new Extensions(fi);
//CertificateExtensions(fi);
return;
} catch (Exception e) {
throw new IOException(e.toString());
}
}
byte[] val = inAttrValue.toByteArray();
Class>[] params = { Object.class };
try {
@SuppressWarnings("unchecked")
Class extClass = (Class) OIDMap.getClass(attributeId);
if (extClass != null) {
Constructor cons = extClass.getConstructor(params);
Object value = Array.newInstance(byte.class, val.length);
for (int i = 0; i < val.length; i++) {
Array.setByte(value, i, val[i]);
}
Object[] passed = new Object[] { value };
attributeValue = cons.newInstance(passed);
} else {
// attribute classes are usable for PKCS10 attributes.
// this is used where the attributes are not actual
// implemented extensions.
attributeValue = new ACertAttrSet(inAttrValue);
}
} catch (InvocationTargetException invk) {
throw new IOException(invk.getTargetException().getMessage(), invk);
} catch (Exception e) {
throw new IOException(e);
}
}
/**
* Constructs an attribute from individual components of ObjectIdentifier
* and the DER encoded value.
*
* @param attributeId the ObjectIdentifier of the attribute.
* @param attributeValue the CertAttrSet.
*/
public PKCS10Attribute(ObjectIdentifier attributeId,
CertAttrSet attributeValue) {
this.attributeId = attributeId;
this.attributeValue = attributeValue;
}
/**
* Constructs an attribute from another attribute. To be used for
* creating decoded subclasses.
*
* @param attr the attribute to create from.
*/
public PKCS10Attribute(PKCS10Attribute attr) {
this.attributeId = attr.attributeId;
this.attributeValue = attr.attributeValue;
}
/**
* Write the output to the DerOutputStream.
*
* @param out the OutputStream to write the attribute to.
* @exception CertificateException on certificate encoding errors.
* @exception IOException on encoding errors.
*/
public void encode(OutputStream out)
throws CertificateException, IOException {
try (DerOutputStream tmp = new DerOutputStream()) {
// Encode the attribute value
DerOutputStream outAttrValue = new DerOutputStream();
attributeValue.encode(outAttrValue);
// Wrap the encoded attribute value into a SET
DerValue outAttrValueSet = new DerValue(DerValue.tag_Set,
outAttrValue.toByteArray());
// Create the attribute
DerOutputStream outAttr = new DerOutputStream();
outAttr.putOID(attributeId);
outAttr.putDerValue(outAttrValueSet);
// Wrap the OID and the set of attribute values into a SEQUENCE
tmp.write(DerValue.tag_Sequence, outAttr);
// write the results to out
out.write(tmp.toByteArray());
}
}
/**
* DER encode this object onto an output stream.
* Implements the DerEncoder
interface.
*
* @param out
* the OutputStream on which to write the DER encoding.
*
* @exception IOException on encoding errors.
*/
@Override
public void derEncode(OutputStream out) throws IOException {
try {
encode(out);
} catch (CertificateException ce) {
IOException ioe = new IOException(ce.toString());
ioe.fillInStackTrace();
throw ioe;
}
}
/**
* Returns the ObjectIdentifier of the attribute.
*/
public ObjectIdentifier getAttributeId() {
return (attributeId);
}
/**
* Returns the attribute value as an byte array for further processing.
*/
public CertAttrSet getAttributeValue() {
return (attributeValue);
}
/**
* Returns the attribute in user readable form.
*/
@Override
public String toString() {
String s = "AttributeId: " + attributeId.toString() + "\n";
s += "AttributeValue: " + attributeValue.toString();
return (s);
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/pkcs/PKCS10Attributes.java 0000664 0000000 0000000 00000012674 14565430767 0031202 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.pkcs;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import org.mozilla.jss.netscape.security.util.DerEncoder;
import org.mozilla.jss.netscape.security.util.DerInputStream;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This class defines the PKCS10 attributes for the request.
*
* @author Amit Kapoor
* @author Hemma Prafullchandra
* @version 1.10
*/
public class PKCS10Attributes extends Vector implements DerEncoder {
public final static Logger logger = LoggerFactory.getLogger(PKCS10Attributes.class);
/**
*
*/
private static final long serialVersionUID = 1362260612357629542L;
private Hashtable map;
/**
* Default constructor for the certificate attribute.
*/
public PKCS10Attributes() {
map = new Hashtable<>();
}
/**
* Create the object, decoding the values from the passed DER stream.
*
* @param in the DerInputStream to read the attributes from.
* @exception IOException on decoding errors.
*/
public PKCS10Attributes(DerInputStream in)
throws IOException {
map = new Hashtable<>();
DerValue[] attrs = in.getSet(5, true);
if (attrs != null) {
for (int i = 0; i < attrs.length; i++) {
PKCS10Attribute attr = new PKCS10Attribute(attrs[i]);
addElement(attr);
logger.debug("PKCS10Attributes: adding attribute: " +
attr.getAttributeValue().getName());
map.put(attr.getAttributeValue().getName(), attr);
}
}
}
/**
* Encode the attributes in DER form to the stream.
*
* @param out the OutputStream to marshal the contents to.
*
* @exception IOException on encoding errors.
*/
public void encode(OutputStream out)
throws IOException {
derEncode(out);
}
/**
* Encode the attributes in DER form to the stream.
* Implements the DerEncoder
interface.
*
* @param out the OutputStream to marshal the contents to.
* @exception IOException on encoding errors.
*/
@Override
public void derEncode(OutputStream out)
throws IOException {
try (DerOutputStream attrOut = new DerOutputStream()) {
// first copy the elements into an array
PKCS10Attribute[] attribs = new PKCS10Attribute[size()];
copyInto(attribs);
attrOut.putOrderedSetOf(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0),
attribs);
out.write(attrOut.toByteArray());
} catch (IOException e) {
throw e;
}
}
/**
* Set the attribute value.
*/
public void setAttribute(String name, PKCS10Attribute attr) throws IOException {
map.put(name, attr);
addElement(attr);
}
/**
* Get the attribute value.
*/
public PKCS10Attribute getAttribute(String name) throws IOException {
PKCS10Attribute attr = map.get(name);
/*
if (attr == null) {
throw new IOException("No attribute found with name " + name);
}
*/
return (attr);
}
/**
* Delete the attribute value.
*/
public void deleteAttribute(String name) throws IOException {
PKCS10Attribute attr = map.get(name);
if (attr == null) {
throw new IOException("No attribute found with name " + name);
}
map.remove(name);
removeElement(attr);
}
/**
* Return an enumeration of names of attributes existing within this
* attribute.
*/
public Enumeration getElements() {
return map.elements();
}
@Override
public synchronized int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((map == null) ? 0 : map.hashCode());
return result;
}
@Override
public synchronized boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
PKCS10Attributes other = (PKCS10Attributes) obj;
if (map == null) {
if (other.map != null)
return false;
} else if (!map.equals(other.map))
return false;
return true;
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/pkcs/PKCS12.java 0000664 0000000 0000000 00000014345 14565430767 0027132 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2016 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.pkcs;
import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import org.mozilla.jss.asn1.OBJECT_IDENTIFIER;
import org.mozilla.jss.pkcs11.PK11Cert;
public class PKCS12 {
// PKI OID: 2.16.840.1.113730.5
public final static OBJECT_IDENTIFIER PKI_OID = new OBJECT_IDENTIFIER("2.16.840.1.113730.5");
// PKCS #12 OID: 2.16.840.1.113730.5.1
public final static OBJECT_IDENTIFIER PKCS12_OID = PKI_OID.subBranch(1);
// PKCS #12 attributes OID: 2.16.840.1.113730.5.1.1
public final static OBJECT_IDENTIFIER PKCS12_ATTRIBUTES_OID = PKCS12_OID.subBranch(1);
// Certificate trust flags OID: 2.16.840.1.113730.5.1.1.1
public final static OBJECT_IDENTIFIER CERT_TRUST_FLAGS_OID = PKCS12_ATTRIBUTES_OID.subBranch(1);
/**
* @deprecated Use PK11Cert.VALID_PEER instead.
*/
@Deprecated
public final static int TERMINAL_RECORD = PK11Cert.VALID_PEER;
/**
* @deprecated Use PK11Cert.TRUSTED_PEER instead.
*/
@Deprecated
public final static int TRUSTED = PK11Cert.TRUSTED_PEER;
/**
* @deprecated Use PK11Cert.SEND_WARN instead.
*/
@Deprecated
public final static int SEND_WARN = PK11Cert.SEND_WARN;
/**
* @deprecated Use PK11Cert.VALID_CA instead.
*/
@Deprecated
public final static int VALID_CA = PK11Cert.VALID_CA;
/**
* @deprecated Use PK11Cert.TRUSTED_CA instead.
*/
@Deprecated
public final static int TRUSTED_CA = PK11Cert.TRUSTED_CA;
/**
* @deprecated Use PK11Cert.NS_TRUSTED_CA instead.
*/
@Deprecated
public final static int NS_TRUSTED_CA = PK11Cert.NS_TRUSTED_CA;
/**
* @deprecated Use PK11Cert.USER instead.
*/
@Deprecated
public final static int USER = PK11Cert.USER;
/**
* @deprecated Use PK11Cert.TRUSTED_CLIENT_CA instead.
*/
@Deprecated
public final static int TRUSTED_CLIENT_CA = PK11Cert.TRUSTED_CLIENT_CA;
/**
* @deprecated Use PK11Cert.INVISIBLE_CA instead.
*/
@Deprecated
public final static int INVISIBLE_CA = PK11Cert.INVISIBLE_CA;
/**
* @deprecated Use PK11Cert.GOVT_APPROVED_CA instead.
*/
@Deprecated
public final static int GOVT_APPROVED_CA = PK11Cert.GOVT_APPROVED_CA;
/**
* @deprecated Use PK11Cert.isTrustFlagEnabled() instead.
*/
@Deprecated
public static boolean isFlagEnabled(int flag, int flags) {
return PK11Cert.isTrustFlagEnabled(flag, flags);
}
/**
* @deprecated Use PK11Cert.encodeTrustFlags() instead.
*/
@Deprecated
public static String encodeFlags(int flags) {
return PK11Cert.encodeTrustFlags(flags);
}
/**
* @deprecated Use PK11Cert.decodeTrustFlags() instead.
*/
@Deprecated
public static int decodeFlags(String flags) throws Exception {
return PK11Cert.decodeTrustFlags(flags);
}
Map keyInfosByID = new LinkedHashMap<>();
Map certInfosByID = new LinkedHashMap<>();
Map certInfosByKeyID = new LinkedHashMap<>();
public PKCS12() {
}
public Collection getKeyInfos() {
return keyInfosByID.values();
}
public void addKeyInfo(PKCS12KeyInfo keyInfo) {
keyInfosByID.put(new BigInteger(1, keyInfo.getID()), keyInfo);
}
public PKCS12KeyInfo getKeyInfoByID(byte[] id) {
return keyInfosByID.get(new BigInteger(1, id));
}
public PKCS12KeyInfo removeKeyInfoByID(byte[] id) {
return keyInfosByID.remove(new BigInteger(1, id));
}
public Collection getCertInfos() {
return certInfosByID.values();
}
public void addCertInfo(PKCS12CertInfo certInfo, boolean replace) {
BigInteger id = new BigInteger(1, certInfo.getID());
if (!replace && certInfosByID.containsKey(id))
return;
certInfosByID.put(id, certInfo);
byte[] keyID = certInfo.getKeyID();
if (keyID == null) return;
certInfosByKeyID.put(new BigInteger(1, keyID), certInfo);
}
public PKCS12CertInfo getCertInfoByID(byte[] id) {
return certInfosByID.get(new BigInteger(1, id));
}
public PKCS12CertInfo getCertInfoByKeyID(byte[] keyID) {
return certInfosByKeyID.get(new BigInteger(1, keyID));
}
public Collection getCertInfosByFriendlyName(String friendlyName) {
Collection result = new ArrayList<>();
for (PKCS12CertInfo certInfo : certInfosByID.values()) {
if (!friendlyName.equals(certInfo.getFriendlyName())) continue;
result.add(certInfo);
}
return result;
}
public void removeCertInfoByFriendlyName(String friendlyName) throws Exception {
Collection result = getCertInfosByFriendlyName(friendlyName);
if (result.isEmpty()) {
throw new Exception("Certificate not found: " + friendlyName);
}
for (PKCS12CertInfo certInfo : result) {
BigInteger id = new BigInteger(1, certInfo.getID());
certInfosByID.remove(id);
byte[] keyID = certInfo.getKeyID();
if (keyID == null) continue;
certInfosByKeyID.remove(new BigInteger(1, keyID));
keyInfosByID.remove(new BigInteger(1, keyID));
}
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/pkcs/PKCS12CertInfo.java 0000664 0000000 0000000 00000003471 14565430767 0030562 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2016 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.pkcs;
import org.mozilla.jss.netscape.security.x509.X509CertImpl;
public class PKCS12CertInfo {
private byte[] id;
private X509CertImpl cert;
private String friendlyName;
private String trustFlags;
private byte[] keyID;
public PKCS12CertInfo() {
}
public byte[] getID() {
return id;
}
public void setID(byte[] id) {
this.id = id;
}
public X509CertImpl getCert() {
return cert;
}
public void setCert(X509CertImpl cert) {
this.cert = cert;
}
public String getFriendlyName() {
return friendlyName;
}
public void setFriendlyName(String friendlyName) {
this.friendlyName = friendlyName;
}
public String getTrustFlags() {
return trustFlags;
}
public void setTrustFlags(String trustFlags) {
this.trustFlags = trustFlags;
}
public byte[] getKeyID() {
return keyID;
}
public void setKeyID(byte[] keyID) {
this.keyID = keyID;
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/pkcs/PKCS12KeyInfo.java 0000664 0000000 0000000 00000004523 14565430767 0030414 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2016 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.pkcs;
import org.mozilla.jss.crypto.PrivateKey;
/**
* This object is used for carrying key info around.
*
* It does not handle raw key material (but it used to).
*
* FIXME: A clear refactoring opportunity exists. The 'privateKey'
* field (and associated constructor) is only used during export,
* and the 'epkiBytes' field (and associated constructor) is only
* used during import. Therefore this should be two different
* types.
*/
public class PKCS12KeyInfo {
private PrivateKey privateKey;
private byte[] epkiBytes;
private byte[] id;
private String friendlyName;
public PKCS12KeyInfo() {
}
/**
* Construct with a PrivateKey. This constructor is used
* for moving the PrivateKey handle around during export.
*/
public PKCS12KeyInfo(PrivateKey k) {
this.privateKey = k;
}
/** Construct with a (serialised) EncrypedPrivateKeyInfo. This
* constructor is used for moving the EPKI data around during
* import.
*/
public PKCS12KeyInfo(byte[] epkiBytes) {
this.epkiBytes = epkiBytes;
}
public PrivateKey getPrivateKey() {
return this.privateKey;
}
public byte[] getEncryptedPrivateKeyInfoBytes() {
return epkiBytes;
}
public byte[] getID() {
return id;
}
public void setID(byte[] id) {
this.id = id;
}
public String getFriendlyName() {
return friendlyName;
}
public void setFriendlyName(String friendlyName) {
this.friendlyName = friendlyName;
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/pkcs/PKCS12Util.java 0000664 0000000 0000000 00000102155 14565430767 0027765 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2016 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.pkcs;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.math.BigInteger;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.security.MessageDigest;
import java.security.PublicKey;
import java.security.SecureRandom;
import java.security.cert.CertificateException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import javax.naming.InvalidNameException;
import javax.naming.ldap.LdapName;
import javax.naming.ldap.Rdn;
import javax.security.auth.x500.X500Principal;
import org.apache.commons.lang3.StringUtils;
import org.mozilla.jss.CryptoManager;
import org.mozilla.jss.asn1.ANY;
import org.mozilla.jss.asn1.ASN1Value;
import org.mozilla.jss.asn1.BMPString;
import org.mozilla.jss.asn1.OBJECT_IDENTIFIER;
import org.mozilla.jss.asn1.OCTET_STRING;
import org.mozilla.jss.asn1.SEQUENCE;
import org.mozilla.jss.asn1.SET;
import org.mozilla.jss.crypto.CryptoStore;
import org.mozilla.jss.crypto.CryptoToken;
import org.mozilla.jss.crypto.EncryptionAlgorithm;
import org.mozilla.jss.crypto.NoSuchItemOnTokenException;
import org.mozilla.jss.crypto.ObjectNotFoundException;
import org.mozilla.jss.crypto.PBEAlgorithm;
import org.mozilla.jss.crypto.PrivateKey;
import org.mozilla.jss.crypto.X509Certificate;
import org.mozilla.jss.netscape.security.util.Utils;
import org.mozilla.jss.netscape.security.x509.X509CertImpl;
import org.mozilla.jss.pkcs11.PK11Cert;
import org.mozilla.jss.pkcs11.PK11Store;
import org.mozilla.jss.pkcs12.AuthenticatedSafes;
import org.mozilla.jss.pkcs12.CertBag;
import org.mozilla.jss.pkcs12.PFX;
import org.mozilla.jss.pkcs12.PasswordConverter;
import org.mozilla.jss.pkcs12.SafeBag;
import org.mozilla.jss.pkix.primitive.Attribute;
import org.mozilla.jss.pkix.primitive.EncryptedPrivateKeyInfo;
import org.mozilla.jss.util.Password;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class PKCS12Util {
private static Logger logger = LoggerFactory.getLogger(PKCS12Util.class);
public final static String NO_ENCRYPTION = "none";
public final static List SUPPORTED_CERT_ENCRYPTIONS = Arrays.asList(new PBEAlgorithm[] {
null, // none
PBEAlgorithm.PBE_SHA1_RC2_40_CBC
});
public final static List SUPPORTED_KEY_ENCRYPTIONS = Arrays.asList(new PBEAlgorithm[] {
PBEAlgorithm.PBE_PKCS5_PBES2,
PBEAlgorithm.PBE_SHA1_DES3_CBC
});
public final static PBEAlgorithm DEFAULT_CERT_ENCRYPTION = SUPPORTED_CERT_ENCRYPTIONS.get(0);
public final static String DEFAULT_CERT_ENCRYPTION_NAME = NO_ENCRYPTION;
public final static PBEAlgorithm DEFAULT_KEY_ENCRYPTION = SUPPORTED_KEY_ENCRYPTIONS.get(0);
public final static String DEFAULT_KEY_ENCRYPTION_NAME = DEFAULT_KEY_ENCRYPTION.toString();
SecureRandom random;
PBEAlgorithm certEncryption = DEFAULT_CERT_ENCRYPTION;
PBEAlgorithm keyEncryption = DEFAULT_KEY_ENCRYPTION;
boolean trustFlagsEnabled = true;
public PKCS12Util() throws Exception {
random = SecureRandom.getInstance("pkcs11prng", "Mozilla-JSS");
}
public void setCertEncryption(String name) throws Exception {
for (PBEAlgorithm algorithm : SUPPORTED_CERT_ENCRYPTIONS) {
if (algorithm == null) {
if (NO_ENCRYPTION.equals(name)) {
this.certEncryption = null;
return;
}
} else if (algorithm.toString().equals(name)) {
this.certEncryption = algorithm;
return;
}
}
throw new Exception("Unsupported certificate encryption: " + name);
}
public void setCertEncryption(PBEAlgorithm algorithm) throws Exception {
this.certEncryption = algorithm;
}
public PBEAlgorithm getCertEncryption() {
return certEncryption;
}
public void setKeyEncryption(String name) throws Exception {
for (PBEAlgorithm algorithm : SUPPORTED_KEY_ENCRYPTIONS) {
if (algorithm == null) {
if (NO_ENCRYPTION.equals(name)) {
this.keyEncryption = null;
return;
}
} else if (algorithm.toString().equals(name)) {
this.keyEncryption = algorithm;
return;
}
}
throw new Exception("Unsupported key encryption: " + name);
}
public void setKeyEncryption(PBEAlgorithm algorithm) throws Exception {
this.keyEncryption = algorithm;
}
public PBEAlgorithm getKeyEncryption() {
return keyEncryption;
}
public boolean isTrustFlagsEnabled() {
return trustFlagsEnabled;
}
public void setTrustFlagsEnabled(boolean trustFlagsEnabled) {
this.trustFlagsEnabled = trustFlagsEnabled;
}
/**
* @deprecated Use PK11Cert.getTrustFlags() instead.
*/
@Deprecated
public String getTrustFlags(X509Certificate cert) {
PK11Cert pk11Cert = (PK11Cert) cert;
return pk11Cert.getTrustFlags();
}
/**
* @deprecated Use PK11Cert.setTrustFlags() instead.
*/
@Deprecated
public void setTrustFlags(X509Certificate cert, String trustFlags) throws Exception {
PK11Cert pk11Cert = (PK11Cert) cert;
pk11Cert.setTrustFlags(trustFlags);
}
/**
* Add a private key to the PKCS #12 object.
*
* The PKCS12KeyInfo object received comes about in two
* different scenarios:
*
* - The private key could be in encrypted byte[] form (e.g.
* when we have merely loaded a PKCS #12 file for inspection
* or e.g. to delete a certificate and its associated key).
* In this case we simply re-use this encrypted private key
* info byte[].
*
* - The private key could be a be an NSS PrivateKey handle. In
* this case we must export the PrivateKey from the token to
* obtain the EncryptedPrivateKeyInfo.
*
* The common final step is to add the encrypted private key
* data to a "Shrouded Key Bag" to the PKCS #12 object.
* Unencrypted key material is never seen.
*/
public void addKeyBag(PKCS12KeyInfo keyInfo, Password password,
SEQUENCE encSafeContents) throws Exception {
byte[] keyID = keyInfo.getID();
logger.debug(" - Key ID: " + Utils.HexEncode(keyID));
ASN1Value content;
byte[] epkiBytes = keyInfo.getEncryptedPrivateKeyInfoBytes();
if (epkiBytes != null) {
// private key already encrypted
content = new ANY(epkiBytes);
} else {
PrivateKey privateKey = keyInfo.getPrivateKey();
if (privateKey == null) {
throw new Exception("Missing private key for " + keyInfo.getFriendlyName());
}
CryptoToken token = CryptoManager.getInstance().getInternalKeyStorageToken();
if (keyEncryption == PBEAlgorithm.PBE_SHA1_DES3_CBC) {
content = create_EPKI_with_PBE_SHA1_DES3_CBC(token, privateKey, password);
} else if (keyEncryption == PBEAlgorithm.PBE_PKCS5_PBES2) {
content = create_EPKI_with_PBE_PKCS5_PBES2(token, privateKey, password);
} else {
throw new Exception("Unsupported key encryption: " + keyEncryption);
}
}
SET keyAttrs = createKeyBagAttrs(keyInfo);
SafeBag safeBag = new SafeBag(SafeBag.PKCS8_SHROUDED_KEY_BAG, content, keyAttrs);
encSafeContents.addElement(safeBag);
}
public ASN1Value create_EPKI_with_PBE_SHA1_DES3_CBC(CryptoToken token, PrivateKey privateKey, Password password)
throws Exception {
// Use the same salt size and number of iterations as in pk12util.
byte[] salt = new byte[16];
random.nextBytes(salt);
return EncryptedPrivateKeyInfo.createPBE(
PBEAlgorithm.PBE_SHA1_DES3_CBC,
password,
salt,
100000, // iterations
new PasswordConverter(),
privateKey,
token);
}
public ASN1Value create_EPKI_with_PBE_PKCS5_PBES2(CryptoToken token, PrivateKey privateKey, Password password)
throws Exception {
CryptoStore store = token.getCryptoStore();
byte[] bytes = store.getEncryptedPrivateKeyInfo(
// For compatibility with OpenSSL and NSS >= 3.31,
// do not BMPString-encode the passphrase when using
// non-PKCS #12 PBE scheme such as PKCS #5 PBES2.
//
// The resulting PKCS #12 is not compatible with
// NSS < 3.31.
null, // password converter
password,
// NSS has a bug that causes any AES CBC encryption
// to use AES-256, but AlgorithmID contains chosen
// alg. To avoid mismatch, use AES_256_CBC.
EncryptionAlgorithm.AES_256_CBC,
0, // iterations (default)
privateKey);
return new ANY(bytes);
}
public void addCertBag(PKCS12CertInfo certInfo,
SEQUENCE safeContents) throws Exception {
byte[] id = certInfo.getID();
logger.debug(" - Certificate ID: " + Utils.HexEncode(id));
X509CertImpl cert = certInfo.getCert();
ASN1Value certAsn1 = new OCTET_STRING(cert.getEncoded());
CertBag certBag = new CertBag(CertBag.X509_CERT_TYPE, certAsn1);
SET certAttrs = createCertBagAttrs(certInfo);
SafeBag safeBag = new SafeBag(SafeBag.CERT_BAG, certBag, certAttrs);
safeContents.addElement(safeBag);
}
BigInteger createLocalID(X509Certificate cert) throws Exception {
// SHA1 hash of the X509Cert DER encoding
return createLocalID(cert.getEncoded());
}
BigInteger createLocalID(byte[] bytes) throws Exception {
MessageDigest md = MessageDigest.getInstance("SHA");
md.update(bytes);
return new BigInteger(1, md.digest());
}
SET createKeyBagAttrs(PKCS12KeyInfo keyInfo) throws Exception {
SET attrs = new SET();
String friendlyName = keyInfo.getFriendlyName();
logger.debug(" Friendly name: " + friendlyName);
SEQUENCE subjectAttr = new SEQUENCE();
subjectAttr.addElement(SafeBag.FRIENDLY_NAME);
SET subjectSet = new SET();
subjectSet.addElement(new BMPString(friendlyName));
subjectAttr.addElement(subjectSet);
attrs.addElement(subjectAttr);
byte[] keyID = keyInfo.getID();
SEQUENCE localKeyAttr = new SEQUENCE();
localKeyAttr.addElement(SafeBag.LOCAL_KEY_ID);
SET localKeySet = new SET();
localKeySet.addElement(new OCTET_STRING(keyID));
localKeyAttr.addElement(localKeySet);
attrs.addElement(localKeyAttr);
return attrs;
}
SET createCertBagAttrs(PKCS12CertInfo certInfo) throws Exception {
SET attrs = new SET();
String friendlyName = certInfo.getFriendlyName();
logger.debug(" Friendly name: " + friendlyName);
SEQUENCE nicknameAttr = new SEQUENCE();
nicknameAttr.addElement(SafeBag.FRIENDLY_NAME);
SET nicknameSet = new SET();
nicknameSet.addElement(new BMPString(friendlyName));
nicknameAttr.addElement(nicknameSet);
attrs.addElement(nicknameAttr);
String trustFlags = certInfo.getTrustFlags();
if (trustFlags != null && trustFlagsEnabled) {
logger.debug(" Trust flags: " + trustFlags);
SEQUENCE trustFlagsAttr = new SEQUENCE();
trustFlagsAttr.addElement(PKCS12.CERT_TRUST_FLAGS_OID);
SET trustFlagsSet = new SET();
trustFlagsSet.addElement(new BMPString(trustFlags));
trustFlagsAttr.addElement(trustFlagsSet);
attrs.addElement(trustFlagsAttr);
}
byte[] keyID = certInfo.getKeyID();
if (keyID != null) {
logger.debug(" Key ID: " + Utils.HexEncode(keyID));
SEQUENCE localKeyAttr = new SEQUENCE();
localKeyAttr.addElement(SafeBag.LOCAL_KEY_ID);
SET localKeySet = new SET();
localKeySet.addElement(new OCTET_STRING(keyID));
localKeyAttr.addElement(localKeySet);
attrs.addElement(localKeyAttr);
}
return attrs;
}
public void loadFromNSS(PKCS12 pkcs12) throws Exception {
loadFromNSS(pkcs12, true, true);
}
public void loadFromNSS(PKCS12 pkcs12, boolean includeKey, boolean includeChain) throws Exception {
logger.info("Loading certificates and keys from NSS database");
CryptoManager cm = CryptoManager.getInstance();
CryptoToken token = cm.getInternalKeyStorageToken();
CryptoStore store = token.getCryptoStore();
for (X509Certificate cert : store.getCertificates()) {
loadCertFromNSS(pkcs12, cert, includeKey, includeChain);
}
}
public void loadCertFromNSS(
PKCS12 pkcs12,
String nickname,
boolean includeKey,
boolean includeChain) throws Exception {
loadCertFromNSS(pkcs12, nickname, includeKey, includeChain, null);
}
public void loadCertFromNSS(
PKCS12 pkcs12,
String nickname,
boolean includeKey,
boolean includeChain,
String friendlyName) throws Exception {
CryptoManager cm = CryptoManager.getInstance();
X509Certificate[] certs = cm.findCertsByNickname(nickname);
if (certs == null || certs.length == 0) {
throw new Exception("Certificate not found: " + nickname);
}
for (X509Certificate cert : certs) {
loadCertFromNSS(pkcs12, cert, includeKey, includeChain, friendlyName);
}
}
public void loadCertFromNSS(
PKCS12 pkcs12,
X509Certificate cert,
boolean includeKey,
boolean includeChain) throws Exception {
loadCertFromNSS(pkcs12, cert, includeKey, includeChain, null);
}
public void loadCertFromNSS(
PKCS12 pkcs12,
X509Certificate cert,
boolean includeKey,
boolean includeChain,
String friendlyName) throws Exception {
CryptoManager cm = CryptoManager.getInstance();
PKCS12CertInfo certInfo = createCertInfoFromNSS(cert, friendlyName);
pkcs12.addCertInfo(certInfo, true);
byte[] id = certInfo.getID();
logger.debug(" - Certificate ID: " + Utils.HexEncode(id));
logger.debug(" Friendly name: " + certInfo.getFriendlyName());
logger.debug(" Trust flags: " + certInfo.getTrustFlags());
if (includeKey) {
// load key info if exists
try {
PrivateKey privateKey = cm.findPrivKeyByCert(cert);
PKCS12KeyInfo keyInfo = createKeyInfoFromNSS(cert, privateKey, friendlyName);
pkcs12.addKeyInfo(keyInfo);
byte[] keyID = keyInfo.getID();
certInfo.setKeyID(keyID);
logger.debug(" Key ID: " + Utils.HexEncode(keyID));
} catch (ObjectNotFoundException e) {
logger.debug("Certificate has no private key");
}
}
if (includeChain) {
// load cert chain
X509Certificate[] certChain = cm.buildCertificateChain(cert);
if (certChain.length > 1) {
logger.debug(" Certificate Chain:");
}
for (int i = 1; i < certChain.length; i++) {
X509Certificate caCert = certChain[i];
PKCS12CertInfo caCertInfo = createCertInfoFromNSS(caCert);
pkcs12.addCertInfo(caCertInfo, false);
byte[] caCertID = caCertInfo.getID();
logger.debug(" - Certificate ID: " + Utils.HexEncode(caCertID));
logger.debug(" Friendly name: " + caCertInfo.getFriendlyName());
logger.debug(" Trust flags: " + caCertInfo.getTrustFlags());
}
}
}
public PKCS12CertInfo createCertInfoFromNSS(
X509Certificate cert) throws Exception {
return createCertInfoFromNSS(cert, null);
}
public PKCS12CertInfo createCertInfoFromNSS(
X509Certificate cert,
String friendlyName) throws Exception {
// generate cert ID from SHA-1 hash of cert data
byte[] id = SafeBag.getLocalKeyIDFromCert(cert.getEncoded());
if (friendlyName == null) {
friendlyName = cert.getNickname();
}
X509CertImpl certImpl = new X509CertImpl(cert.getEncoded());
PK11Cert p11Cert = (PK11Cert) cert;
String trustFlags = p11Cert.getTrustFlags();
PKCS12CertInfo certInfo = new PKCS12CertInfo();
certInfo.setID(id);
certInfo.setFriendlyName(friendlyName);
certInfo.setCert(certImpl);
certInfo.setTrustFlags(trustFlags);
return certInfo;
}
public PKCS12KeyInfo createKeyInfoFromNSS(
X509Certificate cert,
PrivateKey privateKey) throws Exception {
return createKeyInfoFromNSS(cert, privateKey, null);
}
public PKCS12KeyInfo createKeyInfoFromNSS(
X509Certificate cert,
PrivateKey privateKey,
String friendlyName) throws Exception {
byte[] keyID = privateKey.getUniqueID();
if (friendlyName == null) {
friendlyName = cert.getNickname();
}
PKCS12KeyInfo keyInfo = new PKCS12KeyInfo(privateKey);
keyInfo.setID(keyID);
keyInfo.setFriendlyName(friendlyName);
return keyInfo;
}
public PFX generatePFX(PKCS12 pkcs12, Password password) throws Exception {
logger.info("Generating PKCS #12 data");
AuthenticatedSafes authSafes = new AuthenticatedSafes();
Collection keyInfos = pkcs12.getKeyInfos();
Collection certInfos = pkcs12.getCertInfos();
if (!keyInfos.isEmpty()) {
SEQUENCE keySafeContents = new SEQUENCE();
for (PKCS12KeyInfo keyInfo : keyInfos) {
addKeyBag(keyInfo, password, keySafeContents);
}
authSafes.addSafeContents(keySafeContents);
}
if (!certInfos.isEmpty()) {
SEQUENCE certSafeContents = new SEQUENCE();
for (PKCS12CertInfo certInfo : certInfos) {
addCertBag(certInfo, certSafeContents);
}
if (certEncryption == null) {
authSafes.addSafeContents(certSafeContents);
} else if (certEncryption == PBEAlgorithm.PBE_SHA1_RC2_40_CBC) {
byte[] salt = new byte[16];
random.nextBytes(salt);
authSafes.addEncryptedSafeContents(
certEncryption,
password,
salt,
100000, // iterations
certSafeContents);
} else {
throw new Exception("Unsupported certificate encryption: " + certEncryption);
}
}
PFX pfx = new PFX(authSafes);
// Use the same salt size and number of iterations as in pk12util.
byte[] salt = new byte[16];
random.nextBytes(salt);
pfx.computeMacData(password, salt, 100000);
return pfx;
}
public void storeIntoFile(PKCS12 pkcs12, String filename, Password password) throws Exception {
PFX pfx = generatePFX(pkcs12, password);
logger.info("Storing PKCS #12 data into " + filename);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
pfx.encode(bos);
byte[] data = bos.toByteArray();
try (FileOutputStream fos = new FileOutputStream(filename)) {
fos.write(data);
}
}
/**
* Loads key bags (for IMPORT and other operations on existing
* PKCS #12 files). Does not decrypt EncryptedPrivateKeyInfo
* values, but stores them in PKCS12KeyInfo objects for possible
* later use.
*/
public PKCS12KeyInfo getKeyInfo(SafeBag bag, Password password) throws Exception {
PKCS12KeyInfo keyInfo = new PKCS12KeyInfo(bag.getBagContent().getEncoded());
// get key attributes
SET bagAttrs = bag.getBagAttributes();
for (int i = 0; bagAttrs != null && i < bagAttrs.size(); i++) {
Attribute attr = (Attribute) bagAttrs.elementAt(i);
OBJECT_IDENTIFIER oid = attr.getType();
if (oid.equals(SafeBag.FRIENDLY_NAME)) {
SET values = attr.getValues();
ANY value = (ANY) values.elementAt(0);
ByteArrayInputStream bis = new ByteArrayInputStream(value.getEncoded());
BMPString friendlyName = (BMPString) new BMPString.Template().decode(bis);
keyInfo.setFriendlyName(friendlyName.toString());
logger.debug(" Friendly name: " + keyInfo.getFriendlyName());
} else if (oid.equals(SafeBag.LOCAL_KEY_ID)) {
SET values = attr.getValues();
ANY value = (ANY) values.elementAt(0);
ByteArrayInputStream bis = new ByteArrayInputStream(value.getEncoded());
OCTET_STRING keyIdAsn1 = (OCTET_STRING) new OCTET_STRING.Template().decode(bis);
byte[] keyID = keyIdAsn1.toByteArray();
keyInfo.setID(keyID);
} else {
logger.warn(" " + oid + ": " + attr.getValues());
}
}
return keyInfo;
}
public PKCS12CertInfo getCertInfo(SafeBag bag) throws Exception {
PKCS12CertInfo certInfo = new PKCS12CertInfo();
CertBag certBag = (CertBag) bag.getInterpretedBagContent();
OCTET_STRING certStr = (OCTET_STRING) certBag.getInterpretedCert();
byte[] x509cert = certStr.toByteArray();
// generate cert ID from SHA-1 hash of cert data
byte[] id = SafeBag.getLocalKeyIDFromCert(x509cert);
certInfo.setID(id);
logger.debug(" Certificate ID: " + Utils.HexEncode(id));
X509CertImpl cert = new X509CertImpl(x509cert);
certInfo.setCert(cert);
X500Principal subjectDN = cert.getSubjectX500Principal();
logger.debug(" Subject DN: " + subjectDN);
SET bagAttrs = bag.getBagAttributes();
for (int i = 0; bagAttrs != null && i < bagAttrs.size(); i++) {
Attribute attr = (Attribute) bagAttrs.elementAt(i);
OBJECT_IDENTIFIER oid = attr.getType();
if (oid.equals(SafeBag.FRIENDLY_NAME)) {
SET values = attr.getValues();
ANY value = (ANY) values.elementAt(0);
ByteArrayInputStream bis = new ByteArrayInputStream(value.getEncoded());
BMPString friendlyName = (BMPString) (new BMPString.Template()).decode(bis);
certInfo.setFriendlyName(friendlyName.toString());
logger.debug(" Friendly name: " + certInfo.getFriendlyName());
} else if (oid.equals(SafeBag.LOCAL_KEY_ID)) {
SET values = attr.getValues();
ANY value = (ANY) values.elementAt(0);
ByteArrayInputStream bis = new ByteArrayInputStream(value.getEncoded());
OCTET_STRING keyIdAsn1 = (OCTET_STRING) new OCTET_STRING.Template().decode(bis);
byte[] keyID = keyIdAsn1.toByteArray();
certInfo.setKeyID(keyID);
logger.debug(" Key ID: " + Utils.HexEncode(keyID));
} else if (oid.equals(PKCS12.CERT_TRUST_FLAGS_OID) && trustFlagsEnabled) {
SET values = attr.getValues();
ANY value = (ANY) values.elementAt(0);
ByteArrayInputStream is = new ByteArrayInputStream(value.getEncoded());
BMPString trustFlagsAsn1 = (BMPString) (new BMPString.Template()).decode(is);
String trustFlags = trustFlagsAsn1.toString();
certInfo.setTrustFlags(trustFlags);
logger.debug(" Trust flags: " + trustFlags);
} else {
logger.warn(" " + oid + ": " + attr.getValues());
}
}
if (certInfo.getFriendlyName() == null) {
logger.debug(" Generating new friendly name");
LdapName dn = new LdapName(subjectDN.getName());
ArrayList values = new ArrayList<>();
// The getRdns method returns the list in reverse order
// therefore, we must traverse in reverse order.
List rdns = dn.getRdns();
for (int i = rdns.size() - 1; i >= 0; i--) {
Rdn rdn = rdns.get(i);
values.add(rdn.getValue().toString());
}
String friendlyName = StringUtils.join(values, " - ");
certInfo.setFriendlyName(friendlyName);
logger.debug(" Friendly name: " + friendlyName);
}
return certInfo;
}
public void getKeyInfos(PKCS12 pkcs12, PFX pfx, Password password) throws Exception {
logger.debug("Load encrypted private keys:");
AuthenticatedSafes safes = pfx.getAuthSafes();
for (int i = 0; i < safes.getSize(); i++) {
SEQUENCE contents = safes.getSafeContentsAt(password, i);
for (int j = 0; j < contents.size(); j++) {
SafeBag bag = (SafeBag) contents.elementAt(j);
OBJECT_IDENTIFIER oid = bag.getBagType();
if (!oid.equals(SafeBag.PKCS8_SHROUDED_KEY_BAG)) continue;
logger.debug(" - Private key:");
PKCS12KeyInfo keyInfo = getKeyInfo(bag, password);
pkcs12.addKeyInfo(keyInfo);
}
}
}
public void getCertInfos(PKCS12 pkcs12, PFX pfx, Password password) throws Exception {
logger.debug("Loading certificates:");
AuthenticatedSafes safes = pfx.getAuthSafes();
for (int i = 0; i < safes.getSize(); i++) {
SEQUENCE contents = safes.getSafeContentsAt(password, i);
for (int j = 0; j < contents.size(); j++) {
SafeBag bag = (SafeBag) contents.elementAt(j);
OBJECT_IDENTIFIER oid = bag.getBagType();
if (!oid.equals(SafeBag.CERT_BAG)) continue;
logger.debug(" - Certificate:");
PKCS12CertInfo certInfo = getCertInfo(bag);
pkcs12.addCertInfo(certInfo, true);
}
}
}
public PKCS12 loadFromFile(String filename, Password password) throws Exception {
logger.info("Loading PKCS #12 file");
Path path = Paths.get(filename);
byte[] b = Files.readAllBytes(path);
return loadFromByteArray(b, password);
}
public PKCS12 loadFromByteArray(byte[] b, Password password) throws Exception {
ByteArrayInputStream bis = new ByteArrayInputStream(b);
PFX pfx = (PFX) (new PFX.Template()).decode(bis);
PKCS12 pkcs12 = new PKCS12();
StringBuffer reason = new StringBuffer();
boolean valid = pfx.verifyAuthSafes(password, reason);
if (!valid) {
throw new Exception("Unable to validate PKCS #12 file: " + reason);
}
getKeyInfos(pkcs12, pfx, password);
getCertInfos(pkcs12, pfx, password);
return pkcs12;
}
public PKCS12 loadFromFile(String filename) throws Exception {
return loadFromFile(filename, null);
}
public PrivateKey.Type getPrivateKeyType(PublicKey publicKey) {
if (publicKey.getAlgorithm().equals("EC")) {
return PrivateKey.Type.EC;
}
return PrivateKey.Type.RSA;
}
public PKCS12CertInfo getCertBySubjectDN(PKCS12 pkcs12, String subjectDN)
throws CertificateException {
for (PKCS12CertInfo certInfo : pkcs12.getCertInfos()) {
X500Principal certSubjectDN = certInfo.getCert().getSubjectX500Principal();
try {
LdapName certSubjdn = new LdapName(certSubjectDN.toString());
LdapName subjDn = new LdapName(subjectDN);
if(certSubjdn.equals(subjDn)) return certInfo;
} catch (InvalidNameException e) {
return null;
}
}
return null;
}
public void importKey(
PKCS12 pkcs12,
Password password,
String nickname,
PKCS12KeyInfo keyInfo) throws Exception {
PKCS12CertInfo certInfo = pkcs12.getCertInfoByKeyID(keyInfo.getID());
if (certInfo == null) {
logger.debug("Private key has no certificate, ignore");
return;
}
CryptoManager cm = CryptoManager.getInstance();
CryptoToken token = cm.getInternalKeyStorageToken();
PK11Store store = (PK11Store)token.getCryptoStore();
X509CertImpl certImpl = certInfo.getCert();
X509Certificate cert = cm.importCACertPackage(certImpl.getEncoded());
// get public key
PublicKey publicKey = cert.getPublicKey();
byte[] epkiBytes = keyInfo.getEncryptedPrivateKeyInfoBytes();
if (epkiBytes == null) {
logger.debug(
"No EncryptedPrivateKeyInfo for key '"
+ keyInfo.getFriendlyName() + "'; skipping key");
}
try {
// first true without BMPString-encoding the passphrase.
store.importEncryptedPrivateKeyInfo(
null, password, nickname, publicKey, epkiBytes);
} catch (Exception e) {
// if that failed, try again with BMPString-encoded
// passphrase. This is required for PKCS #12 PBE
// schemes and for PKCS #12 files using PBES2 generated
// by NSS < 3.31
store.importEncryptedPrivateKeyInfo(
new PasswordConverter(), password, nickname, publicKey, epkiBytes);
}
// delete the cert again (it will be imported again later
// with the correct nickname)
try {
store.deleteCertOnly(cert);
} catch (NoSuchItemOnTokenException e) {
// this is OK
}
}
/**
* Store a certificate (and key, if present) in NSSDB.
*/
public void storeCertIntoNSS(
PKCS12 pkcs12, Password password,
PKCS12CertInfo certInfo, boolean overwrite)
throws Exception
{
CryptoManager cm = CryptoManager.getInstance();
CryptoToken ct = cm.getInternalKeyStorageToken();
CryptoStore store = ct.getCryptoStore();
String nickname = certInfo.getFriendlyName();
for (X509Certificate cert : cm.findCertsByNickname(nickname)) {
if (!overwrite) {
return;
}
store.deleteCert(cert);
}
X509CertImpl certImpl = certInfo.getCert();
X509Certificate cert;
byte[] keyID = certInfo.getKeyID();
if (keyID != null) { // cert has key
logger.debug("Importing private key for " + certInfo.getFriendlyName());
PKCS12KeyInfo keyInfo = pkcs12.getKeyInfoByID(keyID);
importKey(pkcs12, password, certInfo.getFriendlyName(), keyInfo);
logger.debug("Importing user certificate " + certInfo.getFriendlyName());
cert = cm.importUserCACertPackage(
certImpl.getEncoded(), certInfo.getFriendlyName());
} else { // cert has no key
logger.debug("Importing CA certificate " + certInfo.getFriendlyName());
// Note: JSS does not preserve CA certificate nickname
cert = cm.importCACertPackage(certImpl.getEncoded());
}
String trustFlags = certInfo.getTrustFlags();
if (trustFlags != null && trustFlagsEnabled) {
PK11Cert pk11Cert = (PK11Cert) cert;
pk11Cert.setTrustFlags(trustFlags);
}
}
public void storeCertIntoNSS(PKCS12 pkcs12, Password password, String nickname, boolean overwrite) throws Exception {
Collection certInfos = pkcs12.getCertInfosByFriendlyName(nickname);
for (PKCS12CertInfo certInfo : certInfos) {
storeCertIntoNSS(pkcs12, password, certInfo, overwrite);
}
}
public void storeIntoNSS(
PKCS12 pkcs12, Password password, boolean overwrite)
throws Exception
{
logger.info("Storing data into NSS database");
for (PKCS12CertInfo certInfo : pkcs12.getCertInfos()) {
storeCertIntoNSS(pkcs12, password, certInfo, overwrite);
}
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/pkcs/PKCS7.java 0000664 0000000 0000000 00000041666 14565430767 0027064 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.pkcs;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.StringReader;
import java.io.StringWriter;
import java.math.BigInteger;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Vector;
import org.mozilla.jss.netscape.security.util.BigInt;
import org.mozilla.jss.netscape.security.util.DerInputStream;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
import org.mozilla.jss.netscape.security.util.ObjectIdentifier;
import org.mozilla.jss.netscape.security.util.Utils;
import org.mozilla.jss.netscape.security.x509.AlgorithmId;
import org.mozilla.jss.netscape.security.x509.X500Name;
import org.mozilla.jss.netscape.security.x509.X509CertImpl;
/**
* PKCS7 as defined in RSA Laboratories PKCS7 Technical Note. Profile
* Supports only SignedData
ContentInfo
* type, where to the type of data signed is plain Data.
* For signedData, crls
, attributes
and
* PKCS#6 Extended Certificates are not supported.
*
* @version 1.33 97/12/10
* @author Benjamin Renaud
*/
public class PKCS7 {
public final static String HEADER = "-----BEGIN PKCS7-----";
public final static String FOOTER = "-----END PKCS7-----";
private ObjectIdentifier contentType;
// the ASN.1 members for a signedData (and other) contentTypes
private BigInt version;
private AlgorithmId[] digestAlgorithmIds;
private ContentInfo contentInfo;
private X509Certificate[] certificates;
private SignerInfo[] signerInfos;
/**
* Unmarshals a PKCS7 block from its encoded form, parsing the
* encoded bytes from the InputStream.
*
* @param in an input stream holding at least one PKCS7 block.
* @exception ParsingException on parsing errors.
* @exception IOException on other errors.
*/
public PKCS7(InputStream in) throws ParsingException, IOException {
DataInputStream dis = new DataInputStream(in);
int len = 0;
byte[] newbuf = new byte[len];
byte[] oldbuf = new byte[len];
byte[] data = new byte[len];
do {
newbuf = new byte[dis.available()];
len += dis.available();
dis.readFully(newbuf);
data = new byte[len];
System.arraycopy(oldbuf, 0, data, 0, oldbuf.length);
System.arraycopy(newbuf, 0, data, oldbuf.length, newbuf.length);
oldbuf = new byte[len];
System.arraycopy(data, 0, oldbuf, 0, data.length);
} while (dis.available() > 0);
parse(new DerInputStream(data));
}
/**
* Unmarshals a PKCS7 block from its encoded form, parsing the
* encoded bytes from the DerInputStream.
*
* @param derin a DerInputStream holding at least one PKCS7 block.
* @exception ParsingException on parsing errors.
*/
public PKCS7(DerInputStream derin) throws ParsingException {
parse(derin);
}
/**
* Unmarshals a PKCS7 block from its encoded form, parsing the
* encoded bytes.
*
* @param bytes the encoded bytes.
* @exception ParsingException on parsing errors.
*/
public PKCS7(byte[] bytes) throws ParsingException {
DerInputStream derin = new DerInputStream(bytes);
parse(derin);
}
/**
* Unmarshals a PKCS7 block from PEM format.
*
* @param input the PKCS7 block in PEM format.
* @exception ParsingException on parsing errors.
*/
public PKCS7(String input) throws ParsingException, IOException {
StringBuilder sb = new StringBuilder();
try (StringReader sr = new StringReader(input.trim());
BufferedReader in = new BufferedReader(sr)) {
String line;
// skip everything up to header
String header = null;
while ((line = in.readLine()) != null) {
if (HEADER.equals(line)) {
header = line;
break;
}
}
if (header == null) {
throw new ParsingException("Missing PKCS #7 header");
}
// store everything up to footer
String footer = null;
while ((line = in.readLine()) != null) {
if (FOOTER.equals(line)) {
footer = line;
break;
}
sb.append(line);
}
if (footer == null) {
throw new ParsingException("Missing PKCS #7 footer");
}
}
byte[] bytes = Utils.base64decode(sb.toString());
parse(new DerInputStream(bytes));
}
private void parse(DerInputStream derin) throws ParsingException {
try {
ContentInfo contentInfo = new ContentInfo(derin);
contentType = contentInfo.contentType;
if (contentType.equals(ContentInfo.SIGNED_DATA_OID)) {
parseSignedData(contentInfo.getContent());
} else {
throw new ParsingException("content type " + contentType +
" not supported.");
}
} catch (IOException e) {
ParsingException pe =
new ParsingException("IOException: " + e.getMessage());
pe.fillInStackTrace();
throw pe;
}
}
/**
* Construct an initialized PKCS7 block.
*
* @param digestAlgorithmIds the message digest algorithm identifiers.
* @param contentInfo the content information.
* @param certificates an array of X.509 certificates.
* @param signerInfos an array of signer information.
*/
public PKCS7(AlgorithmId[] digestAlgorithmIds,
ContentInfo contentInfo,
X509Certificate[] certificates,
SignerInfo[] signerInfos) {
version = new BigInt(1);
this.digestAlgorithmIds = digestAlgorithmIds;
this.contentInfo = contentInfo;
this.certificates = certificates;
this.signerInfos = signerInfos;
}
/**
* Construct PKCS7 from an array of certificates.
*
* @param certs Array of certificates.
*/
public PKCS7(X509Certificate[] certs) {
this(new AlgorithmId[0], new ContentInfo(new byte[0]), certs, new SignerInfo[0]);
}
private void parseSignedData(DerValue val)
throws ParsingException, IOException {
DerInputStream dis = val.toDerInputStream();
// Version
version = dis.getInteger();
// digestAlgorithmIds
DerValue[] digestAlgorithmIdVals = dis.getSet(1);
int len = digestAlgorithmIdVals.length;
digestAlgorithmIds = new AlgorithmId[len];
try {
for (int i = 0; i < len; i++) {
DerValue oid = digestAlgorithmIdVals[i];
digestAlgorithmIds[i] = AlgorithmId.parse(oid);
}
} catch (IOException e) {
ParsingException pe =
new ParsingException("Error parsing digest AlgorithmId IDs: " +
e.getMessage());
pe.fillInStackTrace();
throw pe;
}
// contentInfo
contentInfo = new ContentInfo(dis);
/*
* check if certificates (implicit tag) are provided
* (certificates are OPTIONAL)
*/
if ((byte) (dis.peekByte()) == (byte) 0xA0) {
DerValue[] certificateVals = dis.getSet(2, true);
len = certificateVals.length;
certificates = new X509Certificate[len];
for (int i = 0; i < len; i++) {
try {
X509Certificate cert = new
X509CertImpl(certificateVals[i]);
certificates[i] = cert;
} catch (CertificateException e) {
ParsingException pe =
new ParsingException("CertificateException: " +
e.getMessage());
pe.fillInStackTrace();
throw pe;
}
}
}
// check if crls (implicit tag) are provided (crls are OPTIONAL)
if ((byte) (dis.peekByte()) == (byte) 0xA1) {
dis.getSet(0, true);
}
// signerInfos
DerValue[] signerInfoVals = dis.getSet(1);
len = signerInfoVals.length;
signerInfos = new SignerInfo[len];
for (int i = 0; i < len; i++) {
DerInputStream in = signerInfoVals[i].toDerInputStream();
signerInfos[i] = new SignerInfo(in);
}
}
/**
* Encodes the signed data to an output stream.
*
* @param out the output stream to write the encoded data to.
* @exception IOException on encoding errors.
*/
public void encodeSignedData(OutputStream out) throws IOException {
DerOutputStream derout = new DerOutputStream();
encodeSignedData(derout, true);
out.write(derout.toByteArray());
}
/**
* Like method above but not sorted.
*/
public void encodeSignedData(OutputStream out, boolean sort)
throws IOException {
DerOutputStream derout = new DerOutputStream();
encodeSignedData(derout, sort);
out.write(derout.toByteArray());
}
/**
* encode signed data, sort certs by default.
*/
public void encodeSignedData(DerOutputStream out)
throws IOException {
encodeSignedData(out, true);
}
/**
* Encodes the signed data to a DerOutputStream.
*
* @param out the DerOutputStream to write the encoded data to.
* @exception IOException on encoding errors.
*/
public void encodeSignedData(DerOutputStream out, boolean sort)
throws IOException {
DerOutputStream signedData = new DerOutputStream();
// version
signedData.putInteger(version);
// digestAlgorithmIds
signedData.putOrderedSetOf(DerValue.tag_Set, digestAlgorithmIds);
// contentInfo
contentInfo.encode(signedData);
// cast to X509CertImpl[] since X509CertImpl implements DerEncoder
X509CertImpl implCerts[] = new X509CertImpl[certificates.length];
try {
for (int i = 0; i < certificates.length; i++) {
implCerts[i] = (X509CertImpl) certificates[i];
}
} catch (ClassCastException e) {
throw new IOException(
"Certificates in PKCS7 must be of class " +
"org.mozilla.jss.netscape.security.X509CertImpl: " + e.getMessage(), e);
}
// Add the certificate set (tagged with [0] IMPLICIT)
// to the signed data
if (sort) {
signedData.putOrderedSetOf((byte) 0xA0, implCerts);
} else {
signedData.putSet((byte) 0xA0, implCerts);
}
// no crls (OPTIONAL field)
// signerInfos
signedData.putOrderedSetOf(DerValue.tag_Set, signerInfos);
// making it a signed data block
DerValue signedDataSeq = new DerValue(DerValue.tag_Sequence,
signedData.toByteArray());
// making it a content info sequence
ContentInfo block = new ContentInfo(ContentInfo.SIGNED_DATA_OID,
signedDataSeq);
// writing out the contentInfo sequence
block.encode(out);
}
/**
* This verifies a given SignerInfo.
*
* @param info the signer information.
* @param bytes the DER encoded content information.
*
* @exception NoSuchAlgorithmException on unrecognized algorithms.
* @exception SignatureException on signature handling errors.
*/
public SignerInfo verify(SignerInfo info, byte[] bytes)
throws NoSuchAlgorithmException, SignatureException {
return info.verify(this, bytes);
}
/**
* Returns all signerInfos which self-verify.
*
* @param bytes the DER encoded content information.
*
* @exception NoSuchAlgorithmException on unrecognized algorithms.
* @exception SignatureException on signature handling errors.
*/
public SignerInfo[] verify(byte[] bytes)
throws NoSuchAlgorithmException, SignatureException {
Vector intResult = new Vector<>();
for (int i = 0; i < signerInfos.length; i++) {
SignerInfo signerInfo = verify(signerInfos[i], bytes);
if (signerInfo != null) {
intResult.addElement(signerInfo);
}
}
if (intResult.size() != 0) {
SignerInfo[] result = new SignerInfo[intResult.size()];
intResult.copyInto(result);
return result;
}
return null;
}
/**
* Returns all signerInfos which self-verify.
*
* @exception NoSuchAlgorithmException on unrecognized algorithms.
* @exception SignatureException on signature handling errors.
*/
public SignerInfo[] verify()
throws NoSuchAlgorithmException, SignatureException {
return verify(null);
}
/**
* Returns the version number of this PKCS7 block.
*/
public BigInt getVersion() {
return version;
}
/**
* Returns the message digest algorithms specified in this PKCS7 block.
*/
public AlgorithmId[] getDigestAlgorithmIds() {
return digestAlgorithmIds;
}
/**
* Returns the content information specified in this PKCS7 block.
*/
public ContentInfo getContentInfo() {
return contentInfo;
}
/**
* Returns the X.509 certificates listed in this PKCS7 block.
*/
public X509Certificate[] getCertificates() {
return certificates;
}
/**
* Returns the signer's information specified in this PKCS7 block.
*/
public SignerInfo[] getSignerInfos() {
return signerInfos;
}
/**
* Returns the X.509 certificate listed in this PKCS7 block
* which has a matching serial number and Issuer name, or
* null if one is not found.
*
* @param serial the serial number of the certificate to retrieve.
* @param name the Distinguished Name of the Issuer.
*/
public X509Certificate getCertificate(BigInt serial, X500Name name) {
for (int i = 0; i < certificates.length; i++) {
X509Certificate cert = certificates[i];
X500Name thisName = (X500Name) cert.getIssuerDN();
BigInteger tmpSerial = cert.getSerialNumber();
BigInt thisSerial = new BigInt(tmpSerial);
if (serial.equals(thisSerial) && name.equals(thisName)) {
return cert;
}
}
return null;
}
public byte[] getBytes() throws IOException {
ByteArrayOutputStream out = new ByteArrayOutputStream();
encodeSignedData(out);
return out.toByteArray();
}
public String toPEMString() throws IOException {
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw, true);
pw.println(HEADER);
pw.print(Utils.base64encode(getBytes(), true));
pw.println(FOOTER);
return sw.toString();
}
/**
* Returns the PKCS7 block in a printable string form.
*/
@Override
public String toString() {
StringBuffer out = new StringBuffer("PKCS7 :: version: " + version + "\n");
out.append("PKCS7 :: digest AlgorithmIds: " + "\n");
for (int i = 0; i < digestAlgorithmIds.length; i++) {
out.append("\t" + digestAlgorithmIds[i] + "\n");
}
out.append(contentInfo + "\n");
out.append("PKCS7 :: certificates: " + "\n");
for (int i = 0; i < certificates.length; i++) {
out.append("\t" + i + ". " + certificates[i] + "\n");
}
out.append("PKCS7 :: signer infos: " + "\n");
for (int i = 0; i < signerInfos.length; i++) {
out.append("\t" + i + ". " + signerInfos[i] + "\n");
}
return out.toString();
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/pkcs/PKCS8Key.java 0000664 0000000 0000000 00000034526 14565430767 0027533 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.pkcs;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.lang.reflect.InvocationTargetException;
import java.math.BigInteger;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyFactory;
import java.security.NoSuchAlgorithmException;
import java.security.PrivateKey;
import java.security.Provider;
import java.security.Security;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import org.mozilla.jss.netscape.security.util.BigInt;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
import org.mozilla.jss.netscape.security.x509.AlgorithmId;
/**
* Holds a PKCS#8 key, for example a private key
*
* @version 1.30, 97/12/10
* @author Dave Brownell
* @author Benjamin Renaud
*/
public class PKCS8Key implements PrivateKey {
/** use serialVersionUID from JDK 1.1. for interoperability */
private static final long serialVersionUID = -3836890099307167124L;
/* The algorithm information (name, parameters, etc). */
protected AlgorithmId algid;
/* The key bytes, without the algorithm information */
protected byte[] key;
/* The encoded for the key. */
protected byte[] encodedKey;
/* The version for this key */
public static final BigInteger VERSION = BigInteger.valueOf(0);
/**
* Default constructor. The key constructed must have its key
* and algorithm initialized before it may be used, for example
* by using decode
.
*/
public PKCS8Key() {
}
/**
* Construct PKCS#8 subject public key from a DER value. If
* the runtime environment is configured with a specific class for
* this kind of key, a subclass is returned. Otherwise, a generic
* PKCS8Key object is returned.
*
*
* This mechanism gurantees that keys (and algorithms) may be freely manipulated and transferred, without risk of
* losing information. Also, when a key (or algorithm) needs some special handling, that specific need can be
* accomodated.
*
* @param in the DER-encoded SubjectPublicKeyInfo value
* @exception IOException on data format errors
*/
public static PKCS8Key parse(DerValue in) throws IOException {
AlgorithmId algorithm;
PKCS8Key subjectKey;
if (in.tag != DerValue.tag_Sequence)
throw new IOException("corrupt private key");
BigInteger parsedVersion = in.data.getInteger().toBigInteger();
if (!VERSION.equals(parsedVersion)) {
throw new IOException("version mismatch: (supported: " +
VERSION + ", parsed: " +
parsedVersion);
}
algorithm = AlgorithmId.parse(in.data.getDerValue());
try {
subjectKey = buildPKCS8Key(algorithm, in.data.getOctetString());
} catch (InvalidKeyException e) {
throw new IOException("corrupt private key");
}
if (in.data.available() != 0)
throw new IOException("excess private key");
return subjectKey;
}
/**
* Parse the key bits. This may be redefined by subclasses to take
* advantage of structure within the key. For example, RSA public
* keys encapsulate two unsigned integers (modulus and exponent) as
* DER values within the key
bits; Diffie-Hellman and
* DSS/DSA keys encapsulate a single unsigned integer.
*
*
* This function is called when creating PKCS#8 SubjectPublicKeyInfo values using the PKCS8Key member functions,
* such as parse
and decode
.
*
* @exception IOException if a parsing error occurs.
* @exception InvalidKeyException if the key encoding is invalid.
*/
protected void parseKeyBits() throws IOException, InvalidKeyException {
encode();
}
/*
* Factory interface, building the kind of key associated with this
* specific algorithm ID or else returning this generic base class.
* See the description above.
*/
public static PKCS8Key buildPKCS8Key(AlgorithmId algid, byte[] key)
throws IOException, InvalidKeyException {
/*
* Use the algid and key parameters to produce the ASN.1 encoding
* of the key, which will then be used as the input to the
* key factory.
*/
DerOutputStream pkcs8EncodedKeyStream = new DerOutputStream();
encode(pkcs8EncodedKeyStream, algid, key);
PKCS8EncodedKeySpec pkcs8KeySpec = new PKCS8EncodedKeySpec(pkcs8EncodedKeyStream.toByteArray());
try {
// Instantiate the key factory of the appropriate algorithm
KeyFactory keyFac = KeyFactory.getInstance(algid.getName());
// Generate the private key
PrivateKey privKey = keyFac.generatePrivate(pkcs8KeySpec);
if (privKey instanceof PKCS8Key) {
/*
* Return specialized PKCS8Key, where the structure within the
* key has been parsed
*/
return (PKCS8Key) privKey;
}
} catch (NoSuchAlgorithmException e) {
// Return generic PKCS8Key with opaque key data (see below)
} catch (InvalidKeySpecException e) {
// Return generic PKCS8Key with opaque key data (see below)
}
/*
* Try again using JDK1.1-style for backwards compatibility.
*/
String classname = "";
try {
Provider sunProvider;
sunProvider = Security.getProvider("SUN");
if (sunProvider == null)
throw new InstantiationException();
classname = sunProvider.getProperty("PrivateKey.PKCS#8." +
algid.getName());
if (classname == null) {
throw new InstantiationException();
}
Class> keyClass = Class.forName(classname);
Object inst;
PKCS8Key result;
inst = keyClass.getConstructor().newInstance();
if (inst instanceof PKCS8Key) {
result = (PKCS8Key) inst;
result.algid = algid;
result.key = key;
result.parseKeyBits();
return result;
}
} catch (ClassNotFoundException e) {
} catch (InstantiationException e) {
} catch (IllegalAccessException e) {
throw new IOException("IllegalAccessException : " +
e.getMessage(), e);
} catch (NoSuchMethodException e) {
} catch (InvocationTargetException e) {
throw new IOException("InvocationTargetException : " +
e.getMessage(), e);
}
PKCS8Key result = new PKCS8Key();
result.algid = algid;
result.key = key;
return result;
}
/**
* Returns the algorithm to be used with this key.
*/
@Override
public String getAlgorithm() {
return algid.getName();
}
/**
* Returns the algorithm ID to be used with this key.
*/
public AlgorithmId getAlgorithmId() {
return algid;
}
/**
* PKCS#8 sequence on the DER output stream.
*/
public final void encode(DerOutputStream out) throws IOException {
encode(out, this.algid, this.key);
}
/**
* Returns the DER-encoded form of the key as a byte array.
*/
@Override
public synchronized byte[] getEncoded() {
byte[] result = null;
try {
result = encode();
} catch (InvalidKeyException e) {
}
return result;
}
/**
* Returns the format for this key: "PKCS#8"
*/
@Override
public String getFormat() {
return "PKCS#8";
}
/**
* Returns the DER-encoded form of the key as a byte array.
*
* @exception InvalidKeyException if an encoding error occurs.
*/
public byte[] encode() throws InvalidKeyException {
if (encodedKey == null) {
try {
DerOutputStream out;
out = new DerOutputStream();
encode(out);
encodedKey = out.toByteArray();
} catch (IOException e) {
throw new InvalidKeyException("IOException : " +
e.getMessage());
}
}
return copyEncodedKey(encodedKey);
}
/*
* Returns a printable representation of the key
*/
@Override
public String toString() {
org.mozilla.jss.netscape.security.util.PrettyPrintFormat pp =
new org.mozilla.jss.netscape.security.util.PrettyPrintFormat(" ", 20);
String keybits = pp.toHexString(key);
return "algorithm = " + algid.toString()
+ ", unparsed keybits = \n" + keybits;
}
/**
* Initialize an PKCS8Key object from an input stream. The data
* on that input stream must be encoded using DER, obeying the
* PKCS#8 format: a sequence consisting of a version, an algorithm
* ID and a bit string which holds the key. (That bit string is
* often used to encapsulate another DER encoded sequence.)
*
*
* Subclasses should not normally redefine this method; they should instead provide a parseKeyBits
* method to parse any fields inside the key
member.
*
* @param in an input stream with a DER-encoded PKCS#8
* SubjectPublicKeyInfo value
*
* @exception InvalidKeyException if a parsing error occurs.
*/
public void decode(InputStream in) throws InvalidKeyException {
DerValue val;
try {
val = new DerValue(in);
if (val.tag != DerValue.tag_Sequence)
throw new InvalidKeyException("invalid key format");
BigInteger version = val.data.getInteger().toBigInteger();
if (!version.equals(PKCS8Key.VERSION)) {
throw new IOException("version mismatch: (supported: " +
PKCS8Key.VERSION + ", parsed: " +
version);
}
algid = AlgorithmId.parse(val.data.getDerValue());
key = val.data.getOctetString();
parseKeyBits();
if (val.data.available() != 0)
throw new InvalidKeyException("excess key data");
} catch (IOException e) {
throw new InvalidKeyException("IOException : " +
e.getMessage());
}
}
public void decode(byte[] encodedKey) throws InvalidKeyException {
decode(new ByteArrayInputStream(encodedKey));
}
/**
* Serialization write ... PKCS#8 keys serialize as
* themselves, and they're parsed when they get read back.
*/
private void writeObject(java.io.ObjectOutputStream stream) throws IOException {
stream.write(getEncoded());
}
/**
* Serialization read ... PKCS#8 keys serialize as
* themselves, and they're parsed when they get read back.
*/
private void readObject(ObjectInputStream stream) throws IOException {
try {
decode(stream);
} catch (InvalidKeyException e) {
throw new IOException("deserialized key is invalid: " +
e.getMessage());
}
}
/*
* Make a copy of the encoded key.
*/
private byte[] copyEncodedKey(byte[] encodedKey) {
int len = encodedKey.length;
byte[] copy = new byte[len];
System.arraycopy(encodedKey, 0, copy, 0, len);
return copy;
}
/*
* Produce PKCS#8 encoding from algorithm id and key material.
*/
static void encode(DerOutputStream out, AlgorithmId algid, byte[] key)
throws IOException {
DerOutputStream tmp = new DerOutputStream();
tmp.putInteger(new BigInt(VERSION.toByteArray()));
algid.encode(tmp);
tmp.putOctetString(key);
out.write(DerValue.tag_Sequence, tmp);
}
/**
* Compares two private keys. This returns false if the object with which
* to compare is not of type Key
.
* Otherwise, the encoding of this key object is compared with the
* encoding of the given key object.
*
* @param object the object with which to compare
* @return true
if this key has the same encoding as the
* object argument; false
otherwise.
*/
@Override
public boolean equals(Object object) {
if (this == object) {
return true;
}
if (object instanceof Key) {
// this encoding
byte[] b1;
if (encodedKey != null) {
b1 = encodedKey;
} else {
b1 = getEncoded();
}
// that encoding
byte[] b2 = ((Key) object).getEncoded();
// do the comparison
int i;
if (b1.length != b2.length)
return false;
for (i = 0; i < b1.length; i++) {
if (b1[i] != b2[i]) {
return false;
}
}
return true;
}
return false;
}
/**
* Calculates a hash code value for this object. Objects
* which are equal will also have the same hashcode.
*/
@Override
public int hashCode() {
int retval = 0;
byte[] b1 = getEncoded();
for (int i = 1; i < b1.length; i++) {
retval += b1[i] * i;
}
return (retval);
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/pkcs/PKCS9Attribute.java 0000664 0000000 0000000 00000106157 14565430767 0030747 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.pkcs;
import java.io.IOException;
import java.io.OutputStream;
import java.security.cert.CertificateException;
import java.util.Date;
import java.util.Hashtable;
import org.mozilla.jss.netscape.security.util.DerEncoder;
import org.mozilla.jss.netscape.security.util.DerInputStream;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
import org.mozilla.jss.netscape.security.util.ObjectIdentifier;
import org.mozilla.jss.netscape.security.x509.CertificateExtensions;
/**
* Class supporting any PKCS9 attribute except
* ExtendedCertificateAttribute. Supports DER decoding and access to
* attribute values, but not DER encoding or setting of values.
*
* @version 1.2 97/12/10
* @author Douglas Hoover
*/
public class PKCS9Attribute implements DerEncoder {
/*
* OIDs of PKCS #9 attribute types.
*/
private static final String RSADSI_str = "1.2.840.113549";
private static final String PKCS_str = RSADSI_str + ".1";
private static final String PKCS9_str = PKCS_str + ".9";
/**
* Array of attribute OIDs defined in PKCS9, by number.
*/
static final ObjectIdentifier[] PKCS9_OIDS =
//new ObjectIdentifier[10];
// There are some Obsolete(?) attribute identifiers.
// This is mainly for extensionRequest (14) in pkcs10.
// We just add the other 4 as by products.
new ObjectIdentifier[15];
static { // static initializer for PKCS9_OIDS
for (int i = 1; i < PKCS9_OIDS.length; i++) {
PKCS9_OIDS[i] = new ObjectIdentifier(PKCS9_str + "." + i);
}
}
public static final ObjectIdentifier EMAIL_ADDRESS_OID = PKCS9_OIDS[1];
public static final ObjectIdentifier UNSTRUCTURED_NAME_OID = PKCS9_OIDS[2];
public static final ObjectIdentifier CONTENT_TYPE_OID = PKCS9_OIDS[3];
public static final ObjectIdentifier MESSAGE_DIGEST_OID = PKCS9_OIDS[4];
public static final ObjectIdentifier SIGNING_TIME_OID = PKCS9_OIDS[5];
public static final ObjectIdentifier COUNTERSIGNATURE_OID = PKCS9_OIDS[6];
public static final ObjectIdentifier CHALLENGE_PASSWORD_OID = PKCS9_OIDS[7];
public static final ObjectIdentifier UNSTRUCTURED_ADDRESS_OID = PKCS9_OIDS[8];
public static final ObjectIdentifier EXTENDED_CERTIFICATE_ATTRIBUTES_OID = PKCS9_OIDS[9];
public static final ObjectIdentifier ISSUER_AND_SERIALNUMBER_OID = PKCS9_OIDS[10];
public static final ObjectIdentifier PASSWORD_CHECK_OID = PKCS9_OIDS[11];
public static final ObjectIdentifier PUBLIC_KEY_OID = PKCS9_OIDS[12];
public static final ObjectIdentifier SIGNING_DESCRIPTION_OID = PKCS9_OIDS[13];
public static final ObjectIdentifier EXTENSION_REQUEST_OID = PKCS9_OIDS[14];
public static final String EMAIL_ADDRESS_STR = "EmailAddress";
public static final String UNSTRUCTURED_NAME_STR = "UnstructuredName";
public static final String CONTENT_TYPE_STR = "ContentType";
public static final String MESSAGE_DIGEST_STR = "MessageDigest";
public static final String SIGNING_TIME_STR = "SigningTime";
public static final String COUNTERSIGNATURE_STR = "Countersignature";
public static final String CHALLENGE_PASSWORD_STR = "ChallengePassword";
public static final String UNSTRUCTURED_ADDRESS_STR = "UnstructuredAddress";
public static final String EXTENDED_CERTIFICATE_ATTRIBUTES_STR = "ExtendedCertificateAttributes";
public static final String ISSUER_AND_SERIALNUMBER_STR = "IssuerAndSerialNumber";
public static final String PASSWORD_CHECK_STR = "PasswordCheck";
public static final String PUBLIC_KEY_STR = "PublicKey";
public static final String SIGNING_DESCRIPTION_STR = "SigningDescription";
public static final String EXTENSION_REQUEST_STR = "ExtensionRequest";
/**
* Hashtable mapping names and variant names of supported
* attributes to their OIDs. This table contains all name forms
* that occur in PKCS9, in lower case.
*/
private static final Hashtable NAME_OID_TABLE = new Hashtable<>(
28);
static { // static initializer for PCKS9_NAMES
NAME_OID_TABLE.put("emailaddress", PKCS9_OIDS[1]);
NAME_OID_TABLE.put("unstructuredname", PKCS9_OIDS[2]);
NAME_OID_TABLE.put("contenttype", PKCS9_OIDS[3]);
NAME_OID_TABLE.put("messagedigest", PKCS9_OIDS[4]);
NAME_OID_TABLE.put("signingtime", PKCS9_OIDS[5]);
NAME_OID_TABLE.put("countersignature", PKCS9_OIDS[6]);
NAME_OID_TABLE.put("challengepassword", PKCS9_OIDS[7]);
NAME_OID_TABLE.put("unstructuredaddress", PKCS9_OIDS[8]);
NAME_OID_TABLE.put("extendedcertificateattributes", PKCS9_OIDS[9]);
NAME_OID_TABLE.put("issuerandserialNumber", PKCS9_OIDS[10]);
NAME_OID_TABLE.put("passwordcheck", PKCS9_OIDS[11]);
NAME_OID_TABLE.put("publickey", PKCS9_OIDS[12]);
NAME_OID_TABLE.put("signingdescription", PKCS9_OIDS[13]);
NAME_OID_TABLE.put("extensionrequest", PKCS9_OIDS[14]);
};
/**
* Hashtable mapping attribute OIDs defined in PKCS9 to the
* corresponding attribute value type.
*/
private static final Hashtable OID_NAME_TABLE = new Hashtable<>(
14);
static {
OID_NAME_TABLE.put(PKCS9_OIDS[1], EMAIL_ADDRESS_STR);
OID_NAME_TABLE.put(PKCS9_OIDS[2], UNSTRUCTURED_NAME_STR);
OID_NAME_TABLE.put(PKCS9_OIDS[3], CONTENT_TYPE_STR);
OID_NAME_TABLE.put(PKCS9_OIDS[4], MESSAGE_DIGEST_STR);
OID_NAME_TABLE.put(PKCS9_OIDS[5], SIGNING_TIME_STR);
OID_NAME_TABLE.put(PKCS9_OIDS[6], COUNTERSIGNATURE_STR);
OID_NAME_TABLE.put(PKCS9_OIDS[7], CHALLENGE_PASSWORD_STR);
OID_NAME_TABLE.put(PKCS9_OIDS[8], UNSTRUCTURED_ADDRESS_STR);
OID_NAME_TABLE.put(PKCS9_OIDS[9], EXTENDED_CERTIFICATE_ATTRIBUTES_STR);
OID_NAME_TABLE.put(PKCS9_OIDS[10], ISSUER_AND_SERIALNUMBER_STR);
OID_NAME_TABLE.put(PKCS9_OIDS[11], PASSWORD_CHECK_STR);
OID_NAME_TABLE.put(PKCS9_OIDS[12], PUBLIC_KEY_STR);
OID_NAME_TABLE.put(PKCS9_OIDS[13], SIGNING_DESCRIPTION_STR);
OID_NAME_TABLE.put(PKCS9_OIDS[14], EXTENSION_REQUEST_STR);
}
/**
* Acceptable ASN.1 tags for DER encodings of values of PKCS9
* attributes, by index in PKCS9_OIDS
.
* Sets of acceptable tags are represented as arrays.
*/
private static final Byte[][] PKCS9_VALUE_TAGS = {
null,
{ Byte.valueOf(DerValue.tag_IA5String) }, // EMailAddress
{ Byte.valueOf(DerValue.tag_IA5String) }, // UnstructuredName
{ Byte.valueOf(DerValue.tag_ObjectId) }, // ContentType
{ Byte.valueOf(DerValue.tag_OctetString) }, // MessageDigest
{ Byte.valueOf(DerValue.tag_UtcTime) }, // SigningTime
{ Byte.valueOf(DerValue.tag_Sequence) }, // Countersignature
{ Byte.valueOf(DerValue.tag_PrintableString),
Byte.valueOf(DerValue.tag_T61String) }, // ChallengePassword
{ Byte.valueOf(DerValue.tag_PrintableString),
Byte.valueOf(DerValue.tag_T61String) }, // UnstructuredAddress
{ Byte.valueOf(DerValue.tag_SetOf) }, // ExtendedCertificateAttributes
null, //IssuerAndSerialNumber
null, //PasswordCheck
null, //PublicKey
null, //SigningDescription
{ Byte.valueOf(DerValue.tag_Sequence) } //ExtensionRequest
};
/**
* Class types required for values for a given PKCS9
* attribute type.
*
*
* The following table shows the correspondence between attribute types and value component classes.
*
*
*
*
*
* OID |
* Attribute Type Name |
* Kind |
* Value Class |
*
*
*
* 1.2.840.113549.1.9.1 |
* EmailAddress |
* Multiple-valued |
* String[] |
*
*
*
* 1.2.840.113549.1.9.2 |
* UnstructuredName |
* Multiple-valued |
* String |
*
*
*
* 1.2.840.113549.1.9.3 |
* ContentType |
* Single-valued |
* ObjectIdentifier |
*
*
*
* 1.2.840.113549.1.9.4 |
* MessageDigest |
* Single-valued |
* byte[] |
*
*
*
* 1.2.840.113549.1.9.5 |
* SigningTime |
* Single-valued |
* Date |
*
*
*
* 1.2.840.113549.1.9.6 |
* Countersignature |
* Multiple-valued |
* SignerInfo |
*
*
*
* 1.2.840.113549.1.9.7 |
* ChallengePassword |
* Single-valued |
* String |
*
*
*
* 1.2.840.113549.1.9.8 |
* UnstructuredAddress |
* Single-valued |
* String |
*
*
*
* 1.2.840.113549.1.9.9 |
* ExtendedCertificateAttributes |
* Multiple-valued |
* (not supported) |
*
*
*
* 1.2.840.113549.1.9.10 |
* IssuerAndSerialNumber |
* Single-valued |
* (not supported) |
*
*
*
* 1.2.840.113549.1.9.11 |
* PasswordCheck |
* Single-valued |
* (not supported) |
*
*
*
* 1.2.840.113549.1.9.12 |
* PublicKey |
* Single-valued |
* (not supported) |
*
*
*
* 1.2.840.113549.1.9.13 |
* SigningDescription |
* Single-valued |
* (not supported) |
*
*
*
* 1.2.840.113549.1.9.14 |
* ExtensionRequest |
* Single-valued |
* Sequence |
*
*
*
*/
private static final Class>[] VALUE_CLASSES = new Class[15];
static {
VALUE_CLASSES[0] = null; // not used
VALUE_CLASSES[1] = String[].class; // EMailAddress
VALUE_CLASSES[2] = String[].class; // UnstructuredName
VALUE_CLASSES[3] = ObjectIdentifier.class; // ContentType
VALUE_CLASSES[4] = byte[].class; // MessageDigest (byte[])
VALUE_CLASSES[5] = Date.class; // SigningTime
VALUE_CLASSES[6] = SignerInfo[].class; // Countersignature
VALUE_CLASSES[7] = String.class; // ChallengePassword
VALUE_CLASSES[8] = String[].class; // UnstructuredAddress
VALUE_CLASSES[9] = null; // ExtendedCertificateAttributes
VALUE_CLASSES[10] = null; // IssuerAndSerialNumber
VALUE_CLASSES[11] = null; // PasswordCheck
VALUE_CLASSES[12] = null; // PublicKey
VALUE_CLASSES[13] = null; // SigningDescription
VALUE_CLASSES[14] = CertificateExtensions.class; // ExtensionRequest
}
/**
* Array indicating which PKCS9 attributes are single-valued,
* by index in PKCS9_OIDS
.
*/
private static final boolean[] SINGLE_VALUED =
{ false,
false, // EMailAddress
false, // UnstructuredName
true, // ContentType
true, // MessageDigest
true, // SigningTime
false, // Countersignature
true, // ChallengePassword
false, // UnstructuredAddress
false, // ExtendedCertificateAttributes
true, // IssuerAndSerialNumber
true, // PasswordCheck
true, // PublicKey
true, // SigningDescription
true // ExtensionRequest
};
/**
* The OID of this attribute is PKCS9_OIDS[index]
.
*/
private int index;
/**
* Value set of this attribute. Its class is given by VALUE_CLASSES[index]
.
*/
private Object value;
/**
* Construct an attribute object from the attribute's OID and
* value. If the attribute is single-valued, provide only one
* value. If the attribute is
* multiple-valued, provide an array containing all the values.
* Arrays of length zero are accepted, though probably useless.
*
*
* The following table gives the class that value
must have for a given attribute.
*
*
*
* value
*
*
* OID |
* Attribute Type Name |
* Kind |
* Value Class |
*
*
*
* 1.2.840.113549.1.9.1 |
* EmailAddress |
* Multiple-valued |
* String[] |
*
*
*
* 1.2.840.113549.1.9.2 |
* UnstructuredName |
* Multiple-valued |
* String[] |
*
*
*
* 1.2.840.113549.1.9.3 |
* ContentType |
* Single-valued |
* ObjectIdentifier |
*
*
*
* 1.2.840.113549.1.9.4 |
* MessageDigest |
* Single-valued |
* byte[] |
*
*
*
* 1.2.840.113549.1.9.5 |
* SigningTime |
* Single-valued |
* Date |
*
*
*
* 1.2.840.113549.1.9.6 |
* Countersignature |
* Multiple-valued |
* SignerInfo[] |
*
*
*
* 1.2.840.113549.1.9.7 |
* ChallengePassword |
* Single-valued |
* String |
*
*
*
* 1.2.840.113549.1.9.8 |
* UnstructuredAddress |
* Single-valued |
* String[] |
*
*
*
* 1.2.840.113549.1.9.9 |
* ExtendedCertificateAttributes |
* Multiple-valued |
* (not supported) |
*
*
*
* 1.2.840.113549.1.9.10 |
* IssuerAndSerialNumber |
* Single-valued |
* (not supported) |
*
*
*
* 1.2.840.113549.1.9.11 |
* PasswordCheck |
* Single-valued |
* (not supported) |
*
*
*
* 1.2.840.113549.1.9.12 |
* PublicKey |
* Single-valued |
* (not supported) |
*
*
*
* 1.2.840.113549.1.9.13 |
* SigningDescription |
* Single-valued |
* (not supported) |
*
*
*
* 1.2.840.113549.1.9.14 |
* ExtensionRequest |
* Single-valued |
* Sequence |
*
*
*
*/
public PKCS9Attribute(ObjectIdentifier oid, Object value)
throws IllegalArgumentException {
init(oid, value);
}
/**
* Construct an attribute object from the attribute's name and
* value. If the attribute is single-valued, provide only one
* value. If the attribute is
* multiple-valued, provide an array containing all the values.
* Arrays of length zero are accepted, though probably useless.
*
*
* The following table gives the class that value
must have for a given attribute. Reasonable variants
* of these attributes are accepted; in particular, case does not matter.
*
*
*
* value
*
*
* OID |
* Attribute Type Name |
* Kind |
* Value Class |
*
*
*
* 1.2.840.113549.1.9.1 |
* EmailAddress |
* Multiple-valued |
* String[] |
*
*
*
* 1.2.840.113549.1.9.2 |
* UnstructuredName |
* Multiple-valued |
* String[] |
*
*
*
* 1.2.840.113549.1.9.3 |
* ContentType |
* Single-valued |
* ObjectIdentifier |
*
*
*
* 1.2.840.113549.1.9.4 |
* MessageDigest |
* Single-valued |
* byte[] |
*
*
*
* 1.2.840.113549.1.9.5 |
* SigningTime |
* Single-valued |
* Date |
*
*
*
* 1.2.840.113549.1.9.6 |
* Countersignature |
* Multiple-valued |
* SignerInfo[] |
*
*
*
* 1.2.840.113549.1.9.7 |
* ChallengePassword |
* Single-valued |
* String |
*
*
*
* 1.2.840.113549.1.9.8 |
* UnstructuredAddress |
* Single-valued |
* String[] |
*
*
*
* 1.2.840.113549.1.9.9 |
* ExtendedCertificateAttributes |
* Multiple-valued |
* (not supported) |
*
*
*
* 1.2.840.113549.1.9.10 |
* IssuerAndSerialNumber |
* Single-valued |
* (not supported) |
*
*
*
* 1.2.840.113549.1.9.11 |
* PasswordCheck |
* Single-valued |
* (not supported) |
*
*
*
* 1.2.840.113549.1.9.12 |
* PublicKey |
* Single-valued |
* (not supported) |
*
*
*
* 1.2.840.113549.1.9.13 |
* SigningDescription |
* Single-valued |
* (not supported) |
*
*
*
* 1.2.840.113549.1.9.14 |
* ExtensionRequest |
* Single-valued |
* Sequence |
*
*
*
*
* @exception IllegalArgumentException
* if the name
is not recognized of the value
has the wrong type.
*/
public PKCS9Attribute(String name, Object value)
throws IllegalArgumentException {
ObjectIdentifier oid = getOID(name);
if (oid == null)
throw new IllegalArgumentException(
"Unrecognized attribute name " + name +
" constructing PKCS9Attribute.");
init(oid, value);
}
private void init(ObjectIdentifier oid, Object value)
throws IllegalArgumentException {
index = indexOf(oid, PKCS9_OIDS, 1);
if (index == -1)
throw new IllegalArgumentException(
"Unsupported OID " + oid +
" constructing PKCS9Attribute.");
if (!VALUE_CLASSES[index].isInstance(value))
throw new IllegalArgumentException(
"Wrong value class " +
" for attribute " + oid +
" constructing PKCS9Attribute; was " +
value.getClass().toString() + ", should be " +
VALUE_CLASSES[index].toString());
this.value = value;
}
/**
* Construct a PKCS9Attribute from its encoding on an input
* stream.
*
* @exception IOException on parsing error.
*/
public PKCS9Attribute(DerValue derVal) throws IOException {
decode(derVal);
}
/**
* Decode a PKCS9 attribute.
*
* @param val
* the DerValue representing the DER encoding of the attribute.
*/
private void decode(DerValue derVal) throws IOException {
DerInputStream derIn = new DerInputStream(derVal.toByteArray());
DerValue[] val = derIn.getSequence(2);
if (derIn.available() != 0)
throw new IOException("Excess data parsing PKCS9Attribute");
if (val.length != 2)
throw new IOException("PKCS9Attribute doesn't have two components");
DerValue[] elems;
// get the oid
ObjectIdentifier oid = val[0].getOID();
index = indexOf(oid, PKCS9_OIDS, 1);
Byte tag;
if (index == -1)
throw new IOException("Invalid OID for PKCS9 attribute: " +
oid);
elems = new DerInputStream(val[1].toByteArray()).getSet(1);
// check single valued have only one value
if (SINGLE_VALUED[index] && elems.length > 1)
throwSingleValuedException();
// check for illegal element tags
for (int i = 0; i < elems.length; i++) {
tag = Byte.valueOf(elems[i].tag);
if (indexOf(tag, PKCS9_VALUE_TAGS[index], 0) == -1)
throwTagException(tag);
}
switch (index) {
case 1: // email address
case 2: // unstructured name
case 8: // unstructured address
{ // open scope
String[] values = new String[elems.length];
for (int i = 0; i < elems.length; i++)
values[i] = elems[i].getAsString();
value = values;
} // close scope
break;
case 3: // content type
value = elems[0].getOID();
break;
case 4: // message digest
value = elems[0].getOctetString();
break;
case 5: // signing time
value = (new DerInputStream(elems[0].toByteArray())).getUTCTime();
break;
case 6: // countersignature
{ // open scope
SignerInfo[] values = new SignerInfo[elems.length];
for (int i = 0; i < elems.length; i++)
values[i] =
new SignerInfo(elems[i].toDerInputStream());
value = values;
} // close scope
break;
case 7: // challenge password
value = elems[0].getAsString();
break;
case 9: // extended-certificate attribute -- not
// supported
throw new IOException("PKCS9 extended-certificate " +
"attribute not supported.");
case 10: // IssuerAndSerialNumber attribute -- not
// supported
throw new IOException("PKCS9 IssuerAndSerialNumber " +
"attribute not supported.");
case 11: // passwordCheck attribute -- not
// supported
throw new IOException("PKCS9 passwordCheck " +
"attribute not supported.");
case 12: // PublicKey attribute -- not
// supported
throw new IOException("PKCS9 PublicKey " +
"attribute not supported.");
case 13: // SigningDescription attribute -- not
// supported
throw new IOException("PKCS9 SigningDescription " +
"attribute not supported.");
case 14: // ExtensionRequest attribute
value =
new CertificateExtensions(elems[0].toDerInputStream());
break;
default:
throw new IOException("Invalid PKCS9 attribute index: " + index);
}
}
/**
* Write the DER encoding of this attribute to an output stream.
*
*
* N.B.: This method always encodes values of ChallengePassword and UnstructuredAddress attributes as ASN.1
* PrintableString
s, without checking whether they should be encoded as T61String
s.
*/
@Override
public void derEncode(OutputStream out) throws IOException {
try (DerOutputStream temp = new DerOutputStream();
DerOutputStream temp2 = new DerOutputStream();
DerOutputStream derOut = new DerOutputStream()) {
temp.putOID(getOID());
switch (index) {
case 1: // email address
case 2: // unstructured name
{ // open scope
String[] values = (String[]) value;
DerOutputStream[] temps = new
DerOutputStream[values.length];
for (int i = 0; i < values.length; i++) {
temps[i] = new DerOutputStream();
temps[i].putIA5String(values[i]);
}
temp.putOrderedSetOf(DerValue.tag_Set, temps);
} // close scope
break;
case 3: // content type
{
temp2.putOID((ObjectIdentifier) value);
temp.write(DerValue.tag_Set, temp2.toByteArray());
}
break;
case 4: // message digest
{
temp2.putOctetString((byte[]) value);
temp.write(DerValue.tag_Set, temp2.toByteArray());
}
break;
case 5: // signing time
{
temp2.putUTCTime((Date) value);
temp.write(DerValue.tag_Set, temp2.toByteArray());
}
break;
case 6: // countersignature
temp.putOrderedSetOf(DerValue.tag_Set, (DerEncoder[]) value);
break;
case 7: // challenge password
{
temp2.putPrintableString((String) value);
temp.write(DerValue.tag_Set, temp2.toByteArray());
}
break;
case 8: // unstructured address
{ // open scope
String[] values = (String[]) value;
DerOutputStream[] temps = new
DerOutputStream[values.length];
for (int i = 0; i < values.length; i++) {
temps[i] = new DerOutputStream();
temps[i].putPrintableString(values[i]);
}
temp.putOrderedSetOf(DerValue.tag_Set, temps);
} // close scope
break;
case 9: // extended-certificate attribute -- not
// supported
throw new IOException("PKCS9 extended-certificate " +
"attribute not supported.");
case 10: // IssuerAndSerialNumber attribute -- not
// supported
throw new IOException("PKCS9 IssuerAndSerialNumber " +
"attribute not supported.");
case 11: // passwordCheck attribute -- not
// supported
throw new IOException("PKCS9 passwordCheck " +
"attribute not supported.");
case 12: // PublicKey attribute -- not
// supported
throw new IOException("PKCS9 PublicKey " +
"attribute not supported.");
case 13: // SigningDescription attribute -- not
// supported
throw new IOException("PKCS9 SigningDescription " +
"attribute not supported.");
case 14: // ExtensionRequest attribute
try {
//temp2.putSequence((CertificateExtensions) value);
((CertificateExtensions) value).encode(temp2);
temp.write(DerValue.tag_Sequence, temp2.toByteArray());
} catch (CertificateException e) {
throw new IOException("PKCS9 extension attributes not encoded");
}
break;
default:
throw new IOException("Invalid PKCS9 attribute index: " + index);
}
derOut.write(DerValue.tag_Sequence, temp.toByteArray());
out.write(derOut.toByteArray());
}
}
/**
* Get the value of this attribute. If the attribute is
* single-valued, return just the one value. If the attribute is
* multiple-valued, return an array containing all the values.
* It is possible for this array to be of length 0.
*
*
* The following table gives the class of the value returned, depending on the type of this attribute.
*
*
*
* value
*
*
* OID |
* Attribute Type Name |
* Kind |
* Value Class |
*
*
*
* 1.2.840.113549.1.9.1 |
* EmailAddress |
* Multiple-valued |
* String[] |
*
*
*
* 1.2.840.113549.1.9.2 |
* UnstructuredName |
* Multiple-valued |
* String[] |
*
*
*
* 1.2.840.113549.1.9.3 |
* ContentType |
* Single-valued |
* ObjectIdentifier |
*
*
*
* 1.2.840.113549.1.9.4 |
* MessageDigest |
* Single-valued |
* byte[] |
*
*
*
* 1.2.840.113549.1.9.5 |
* SigningTime |
* Single-valued |
* Date |
*
*
*
* 1.2.840.113549.1.9.6 |
* Countersignature |
* Multiple-valued |
* SignerInfo[] |
*
*
*
* 1.2.840.113549.1.9.7 |
* ChallengePassword |
* Single-valued |
* String |
*
*
*
* 1.2.840.113549.1.9.8 |
* UnstructuredAddress |
* Single-valued |
* String[] |
*
*
*
* 1.2.840.113549.1.9.9 |
* ExtendedCertificateAttributes |
* Multiple-valued |
* (not supported) |
*
*
*
* 1.2.840.113549.1.9.10 |
* IssuerAndSerialNumber |
* Single-valued |
* (not supported) |
*
*
*
* 1.2.840.113549.1.9.11 |
* PasswordCheck |
* Single-valued |
* (not supported) |
*
*
*
* 1.2.840.113549.1.9.12 |
* PublicKey |
* Single-valued |
* (not supported) |
*
*
*
* 1.2.840.113549.1.9.13 |
* SigningDescription |
* Single-valued |
* (not supported) |
*
*
*
* 1.2.840.113549.1.9.14 |
* ExtensionRequest |
* Single-valued |
* Sequence |
*
*
*
*
*/
public Object getValue() {
return value;
}
/**
* Show whether this attribute is single-valued.
*/
public boolean isSingleValued() {
return SINGLE_VALUED[index];
}
/**
* Return the OID of this attribute.
*/
public ObjectIdentifier getOID() {
return PKCS9_OIDS[index];
}
/**
* Return the name of this attribute.
*/
public String getName() {
return OID_NAME_TABLE.get(PKCS9_OIDS[index]);
}
/**
* Return the OID for a given attribute name or null if we don't recognize
* the name.
*/
public static ObjectIdentifier getOID(String name) {
return NAME_OID_TABLE.get(name.toLowerCase());
}
/**
* Return the attribute name for a given OID or null if we don't recognize
* the oid.
*/
public static String getName(ObjectIdentifier oid) {
return OID_NAME_TABLE.get(oid);
}
/**
* Returns a string representation of this attribute.
*/
@Override
public String toString() {
StringBuffer buf = new StringBuffer(100);
buf.append("[");
buf.append(OID_NAME_TABLE.get(PKCS9_OIDS[index]));
buf.append(": ");
if (SINGLE_VALUED[index]) {
if (value instanceof byte[]) { // special case for octet string
org.mozilla.jss.netscape.security.util.PrettyPrintFormat pp =
new org.mozilla.jss.netscape.security.util.PrettyPrintFormat(" ", 20);
String valuebits = pp.toHexString(((byte[]) value));
buf.append(valuebits);
} else {
buf.append(value.toString());
}
buf.append("]");
return buf.toString();
} else { // multiple-valued
boolean first = true;
Object[] values = (Object[]) value;
for (int j = 0; j < values.length; j++) {
if (first)
first = false;
else
buf.append(", ");
buf.append(values[j].toString());
}
return buf.toString();
}
}
/**
* Beginning the search at start
, find the first
* index i
such that a[i] = obj
.
*
* @return the index, if found, and -1 otherwise.
*/
static int indexOf(Object obj, Object[] a, int start) {
for (int i = start; i < a.length; i++) {
if (obj.equals(a[i]))
return i;
}
return -1;
}
/**
* Throw an exception when there are multiple values for
* a single-valued attribute.
*/
private void throwSingleValuedException() throws IOException {
throw new IOException("Single-value attribute " +
getOID() + " (" + getName() + ")" +
" has multiple values.");
}
/**
* Throw an exception when the tag on a value encoding is
* wrong for the attribute whose value it is.
*/
private void throwTagException(Byte tag)
throws IOException {
Byte[] expectedTags = PKCS9_VALUE_TAGS[index];
StringBuffer msg = new StringBuffer(100);
msg.append("Value of attribute ");
msg.append(getOID().toString());
msg.append(" (");
msg.append(getName());
msg.append(") has wrong tag: ");
msg.append(tag.toString());
msg.append(". Expected tags: ");
msg.append(expectedTags[0].toString());
for (int i = 1; i < expectedTags.length; i++) {
msg.append(", ");
msg.append(expectedTags[i].toString());
}
msg.append(".");
throw new IOException(msg.toString());
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/pkcs/PKCS9Attributes.java 0000664 0000000 0000000 00000023467 14565430767 0031134 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.pkcs;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Hashtable;
import org.mozilla.jss.netscape.security.util.DerEncoder;
import org.mozilla.jss.netscape.security.util.DerInputStream;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
import org.mozilla.jss.netscape.security.util.ObjectIdentifier;
/**
* A set of attributes of class PKCS9Attribute.
*
* @version 1.2 97/12/10
* @author Douglas Hoover
*/
public class PKCS9Attributes {
/**
* Attributes in this set indexed by OID.
*/
private final Hashtable attributes = new Hashtable<>(3);
/**
* The keys of this hashtable are the OIDs of permitted attributes.
*/
private final Hashtable permittedAttributes;
/**
* The DER encoding of this attribute set. The tag byte must be
* DerValue.tag_SetOf.
*/
private final byte[] derEncoding;
/**
* Construct a set of PKCS9 Attributes from its
* DER encoding on a DerInputStream, accepting only attributes
* with OIDs on the given
* list. If the array is null, accept all attributes supported by
* class PKCS9Attribute.
*
* @param permittedAttributes
* Array of attribute OIDs that will be accepted.
* @param in
* the contents of the DER encoding of the attribute set.
*
* @exception IOException
* on i/o error, encoding syntax error, unacceptable or
* unsupported attribute, or duplicate attribute.
*
* @see PKCS9Attribute
*/
public PKCS9Attributes(ObjectIdentifier[] permittedAttributes,
DerInputStream in) throws IOException {
if (permittedAttributes != null) {
this.permittedAttributes =
new Hashtable<>(permittedAttributes.length);
for (int i = 0; i < permittedAttributes.length; i++)
this.permittedAttributes.put(permittedAttributes[i],
permittedAttributes[i]);
} else {
this.permittedAttributes = null;
}
// derEncoding initialized in decode()
derEncoding = decode(in);
}
/**
* Construct a set of PKCS9 Attributes from its contents of its
* DER encoding on a DerInputStream. Accept all attributes
* supported by class PKCS9Attribute.
*
* @exception IOException
* on i/o error, encoding syntax error, or unsupported or
* duplicate attribute.
*
* @see PKCS9Attribute
*/
public PKCS9Attributes(DerInputStream in) throws IOException {
// anything goes
// derEncoding initialized in decode()
derEncoding = decode(in);
permittedAttributes = null;
}
/**
* Construct a set of PKCS9 Attributes from the given array of
* PCK9 attributes.
* DER encoding on a DerInputStream. All attributes in attribs
must be
* supported by class PKCS9Attribute.
*
* @exception IOException
* on i/o error, encoding syntax error, or unsupported or
* duplicate attribute.
*
* @see PKCS9Attribute
*/
public PKCS9Attributes(PKCS9Attribute[] attribs)
throws IllegalArgumentException, IOException {
ObjectIdentifier oid;
for (int i = 0; i < attribs.length; i++) {
oid = attribs[i].getOID();
if (attributes.containsKey(oid))
throw new IllegalArgumentException(
"PKCSAttribute " + attribs[i].getOID() +
" duplicated while constructing " +
"PKCS9Attributes.");
attributes.put(oid, attribs[i]);
}
derEncoding = generateDerEncoding();
permittedAttributes = null;
}
/**
* Decode this set of PKCS9 attribute set from the contents of its
* DER encoding.
*
* @param buf
* the contents of the DER encoding of the attribute set.
*
* @exception IOException
* on i/o error, encoding syntax error, unacceptable or
* unsupported attribute, or duplicate attribute.
*/
private byte[] decode(DerInputStream in) throws IOException {
DerValue val = in.getDerValue();
// save the DER encoding with its proper tag byte.
byte[] derEncoding = val.toByteArray();
derEncoding[0] = DerValue.tag_SetOf;
DerInputStream derIn = new DerInputStream(derEncoding);
DerValue[] derVals = derIn.getSet(3, true);
PKCS9Attribute attrib;
ObjectIdentifier oid;
for (int i = 0; i < derVals.length; i++) {
attrib = new PKCS9Attribute(derVals[i]);
oid = attrib.getOID();
if (attributes.get(oid) != null)
throw new IOException("Duplicate PKCS9 attribute: " + oid);
if (permittedAttributes != null &&
!permittedAttributes.containsKey(oid))
throw new IOException("Attribute " + oid +
" not permitted in this attribute set");
attributes.put(oid, attrib);
}
return derEncoding;
}
/**
* Put the DER encoding of this PKCS9 attribute set on an
* DerOutputStream, tagged with the given implicit tag.
*
* @param tag the implicit tag to use in the DER encoding.
* @param out the output stream on which to put the DER encoding.
*
* @exception IOException on output error.
*/
public void encode(byte tag, OutputStream out) throws IOException {
out.write(tag);
out.write(derEncoding, 1, derEncoding.length - 1);
}
private byte[] generateDerEncoding() throws IOException {
try (DerOutputStream out = new DerOutputStream()) {
Object[] attribVals = attributes.values().toArray();
out.putOrderedSetOf(DerValue.tag_SetOf,
castToDerEncoder(attribVals));
return out.toByteArray();
}
}
/**
* Return the DER encoding of this attribute set, tagged with
* DerValue.tag_SetOf.
*/
public byte[] getDerEncoding() throws IOException {
return derEncoding.clone();
}
/**
* Get an attribute from this set.
*/
public PKCS9Attribute getAttribute(ObjectIdentifier oid) {
return attributes.get(oid);
}
/**
* Get an attribute from this set.
*/
public PKCS9Attribute getAttribute(String name) {
return attributes.get(PKCS9Attribute.getOID(name));
}
/**
* Get an array of all attributes in this set, in order of OID.
*/
public PKCS9Attribute[] getAttributes() {
PKCS9Attribute[] attribs = new PKCS9Attribute[attributes.size()];
int j = 0;
for (int i = 1; i < PKCS9Attribute.PKCS9_OIDS.length &&
j < attribs.length; i++) {
attribs[j] = getAttribute(PKCS9Attribute.PKCS9_OIDS[i]);
if (attribs[j] != null)
j++;
}
return attribs;
}
/**
* Get an attribute value by OID.
*/
public Object getAttributeValue(ObjectIdentifier oid)
throws IOException {
try {
Object value = getAttribute(oid).getValue();
return value;
} catch (NullPointerException ex) {
throw new IOException("No value found for attribute " + oid);
}
}
/**
* Get an attribute value by type name.
*/
public Object getAttributeValue(String name) throws IOException {
ObjectIdentifier oid = PKCS9Attribute.getOID(name);
if (oid == null)
throw new IOException("Attribute name " + name +
" not recognized or not supported.");
return getAttributeValue(oid);
}
/**
* Returns the PKCS9 block in a printable string form.
*/
@Override
public String toString() {
StringBuffer buf = new StringBuffer(200);
buf.append("PKCS9 Attributes: [\n\t");
PKCS9Attribute value;
boolean first = true;
for (int i = 1; i < PKCS9Attribute.PKCS9_OIDS.length; i++) {
value = getAttribute(PKCS9Attribute.PKCS9_OIDS[i]);
if (value == null)
continue;
// we have a value; print it
if (first)
first = false;
else
buf.append(";\n\t");
buf.append(value.toString());
}
buf.append("\n\t] (end PKCS9 Attributes)");
return buf.toString();
}
/**
* Cast an object array whose components are DerEncoder
s to DerEncoder[]
.
*/
static DerEncoder[] castToDerEncoder(Object[] objs) {
DerEncoder[] encoders = new DerEncoder[objs.length];
for (int i = 0; i < encoders.length; i++)
encoders[i] = (DerEncoder) objs[i];
return encoders;
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/pkcs/ParsingException.java 0000664 0000000 0000000 00000002436 14565430767 0031507 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.pkcs;
import java.io.IOException;
public class ParsingException extends IOException {
/**
*
*/
private static final long serialVersionUID = -8135726194372647410L;
public ParsingException() {
super();
}
public ParsingException(String mesg) {
super(mesg);
}
public ParsingException(String mesg, Throwable cause) {
super(mesg, cause);
}
public ParsingException(Throwable cause) {
super(cause);
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/pkcs/SignerInfo.java 0000664 0000000 0000000 00000027636 14565430767 0030301 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.pkcs;
import java.io.IOException;
import java.io.OutputStream;
import java.security.InvalidKeyException;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.cert.X509Certificate;
import org.mozilla.jss.netscape.security.util.BigInt;
import org.mozilla.jss.netscape.security.util.DerEncoder;
import org.mozilla.jss.netscape.security.util.DerInputStream;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
import org.mozilla.jss.netscape.security.util.ObjectIdentifier;
import org.mozilla.jss.netscape.security.x509.AlgorithmId;
import org.mozilla.jss.netscape.security.x509.X500Name;
/**
* A SignerInfo, as defined in PKCS#7's signedData type.
*
* @author Benjamin Renaud
* @version 1.27 97/12/10
*/
public class SignerInfo implements DerEncoder {
BigInt version;
X500Name issuerName;
BigInt certificateSerialNumber;
AlgorithmId digestAlgorithmId;
AlgorithmId digestEncryptionAlgorithmId;
byte[] encryptedDigest;
PKCS9Attributes authenticatedAttributes;
PKCS9Attributes unauthenticatedAttributes;
public SignerInfo(X500Name issuerName,
BigInt serial,
AlgorithmId digestAlgorithmId,
AlgorithmId digestEncryptionAlgorithmId,
byte[] encryptedDigest) {
this.version = new BigInt(1);
this.issuerName = issuerName;
this.certificateSerialNumber = serial;
this.digestAlgorithmId = digestAlgorithmId;
this.digestEncryptionAlgorithmId = digestEncryptionAlgorithmId;
this.encryptedDigest = encryptedDigest;
}
public SignerInfo(X500Name issuerName,
BigInt serial,
AlgorithmId digestAlgorithmId,
PKCS9Attributes authenticatedAttributes,
AlgorithmId digestEncryptionAlgorithmId,
byte[] encryptedDigest,
PKCS9Attributes unauthenticatedAttributes) {
this.version = new BigInt(1);
this.issuerName = issuerName;
this.certificateSerialNumber = serial;
this.digestAlgorithmId = digestAlgorithmId;
this.authenticatedAttributes = authenticatedAttributes;
this.digestEncryptionAlgorithmId = digestEncryptionAlgorithmId;
this.encryptedDigest = encryptedDigest;
this.unauthenticatedAttributes = unauthenticatedAttributes;
}
public SignerInfo(DerInputStream derin)
throws IOException, ParsingException {
// version
version = derin.getInteger();
// issuerAndSerialNumber
DerValue[] issuerAndSerialNumber = derin.getSequence(2);
byte[] issuerBytes = issuerAndSerialNumber[0].toByteArray();
issuerName = new X500Name(new DerValue(DerValue.tag_Sequence,
issuerBytes));
certificateSerialNumber = issuerAndSerialNumber[1].getInteger();
// digestAlgorithmId
DerValue tmp = derin.getDerValue();
digestAlgorithmId = AlgorithmId.parse(tmp);
/*
* check if set of auth attributes (implicit tag) is provided
* (auth attributes are OPTIONAL)
*/
if ((byte) (derin.peekByte()) == (byte) 0xA0) {
authenticatedAttributes = new PKCS9Attributes(derin);
}
// digestEncryptionAlgorithmId - little RSA naming scheme -
// signature == encryption...
tmp = derin.getDerValue();
digestEncryptionAlgorithmId = AlgorithmId.parse(tmp);
// encryptedDigest
encryptedDigest = derin.getOctetString();
/*
* check if set of unauth attributes (implicit tag) is provided
* (unauth attributes are OPTIONAL)
*/
if (derin.available() != 0 && (byte) (derin.peekByte()) == (byte) 0xA1) {
unauthenticatedAttributes = new PKCS9Attributes(derin);
}
// all done
if (derin.available() != 0) {
throw new ParsingException("extra data at the end");
}
}
public void encode(DerOutputStream out) throws IOException {
derEncode(out);
}
/**
* DER encode this object onto an output stream.
* Implements the DerEncoder
interface.
*
* @param out
* the output stream on which to write the DER encoding.
*
* @exception IOException on encoding error.
*/
@Override
public void derEncode(OutputStream out) throws IOException {
try (DerOutputStream tmp = new DerOutputStream()) {
DerOutputStream seq = new DerOutputStream();
seq.putInteger(version);
DerOutputStream issuerAndSerialNumber = new DerOutputStream();
issuerName.encode(issuerAndSerialNumber);
issuerAndSerialNumber.putInteger(certificateSerialNumber);
seq.write(DerValue.tag_Sequence, issuerAndSerialNumber);
digestAlgorithmId.encode(seq);
// encode authenticated attributes if there are any
if (authenticatedAttributes != null)
authenticatedAttributes.encode((byte) 0xA0, seq);
digestEncryptionAlgorithmId.encode(seq);
seq.putOctetString(encryptedDigest);
// encode unauthenticated attributes if there are any
if (unauthenticatedAttributes != null)
unauthenticatedAttributes.encode((byte) 0xA1, seq);
tmp.write(DerValue.tag_Sequence, seq);
out.write(tmp.toByteArray());
}
}
public X509Certificate getCertificate(PKCS7 block)
throws IOException {
return block.getCertificate(certificateSerialNumber, issuerName);
}
/* Returns null if verify fails, this signerInfo if
verify succeeds. */
SignerInfo verify(PKCS7 block, byte[] data)
throws NoSuchAlgorithmException, SignatureException {
try {
ContentInfo content = block.getContentInfo();
if (data == null) {
data = content.getContentBytes();
}
String digestAlgname =
getDigestAlgorithmId().getName();
byte[] dataSigned;
// if there are authenticate attributes, get the message
// digest and compare it with the digest of data
if (authenticatedAttributes == null) {
dataSigned = data;
} else {
// first, check content type
ObjectIdentifier contentType = (ObjectIdentifier)
authenticatedAttributes.getAttributeValue(
PKCS9Attribute.CONTENT_TYPE_OID);
if (contentType == null ||
!contentType.equals(content.contentType))
return null; // contentType does not match, bad SignerInfo
// now, check message digest
byte[] messageDigest = (byte[])
authenticatedAttributes.getAttributeValue(
PKCS9Attribute.MESSAGE_DIGEST_OID);
if (messageDigest == null) // fail if there is no message digest
return null;
MessageDigest md = MessageDigest.getInstance(digestAlgname);
byte[] computedMessageDigest = md.digest(data);
if (messageDigest.length != computedMessageDigest.length)
return null;
for (int i = 0; i < messageDigest.length; i++) {
if (messageDigest[i] != computedMessageDigest[i])
return null;
}
// message digest attribute matched
// digest of original data
// the data actually signed is the DER encoding of
// the authenticated attributes (tagged with
// the "SET OF" tag, not 0xA0).
dataSigned = authenticatedAttributes.getDerEncoding();
}
// put together digest algorithm and encryption algorithm
// to form signing algorithm
String encryptionAlgname =
getDigestEncryptionAlgorithmId().getName();
String algname;
if (encryptionAlgname.equals("DSA") ||
encryptionAlgname.equals("SHA1withDSA")) {
algname = "DSA";
} else {
algname = digestAlgname + "/" + encryptionAlgname;
}
Signature sig = Signature.getInstance(algname);
X509Certificate cert = getCertificate(block);
if (cert == null) {
return null;
}
PublicKey key = cert.getPublicKey();
sig.initVerify(key);
sig.update(dataSigned);
if (sig.verify(encryptedDigest)) {
return this;
}
} catch (IOException e) {
throw new SignatureException("IO error verifying signature:\n" +
e.getMessage());
} catch (InvalidKeyException e) {
throw new SignatureException("InvalidKey: " + e.getMessage());
}
return null;
}
/* Verify the content of the pkcs7 block. */
SignerInfo verify(PKCS7 block)
throws NoSuchAlgorithmException, SignatureException {
return verify(block, null);
}
public BigInt getVersion() {
return version;
}
public X500Name getIssuerName() {
return issuerName;
}
public BigInt getCertificateSerialNumber() {
return certificateSerialNumber;
}
public AlgorithmId getDigestAlgorithmId() {
return digestAlgorithmId;
}
public PKCS9Attributes getAuthenticatedAttributes() {
return authenticatedAttributes;
}
public AlgorithmId getDigestEncryptionAlgorithmId() {
return digestEncryptionAlgorithmId;
}
public byte[] getEncryptedDigest() {
return encryptedDigest;
}
public PKCS9Attributes getUnauthenticatedAttributes() {
return unauthenticatedAttributes;
}
@Override
public String toString() {
org.mozilla.jss.netscape.security.util.PrettyPrintFormat pp =
new org.mozilla.jss.netscape.security.util.PrettyPrintFormat(" ", 20);
String digestbits = pp.toHexString(encryptedDigest);
String out = "";
out += "Signer Info for (issuer): " + issuerName + "\n";
out += "\tversion: " + version + "\n";
out += "\tcertificateSerialNumber: " + certificateSerialNumber +
"\n";
out += "\tdigestAlgorithmId: " + digestAlgorithmId + "\n";
if (authenticatedAttributes != null) {
out += "\tauthenticatedAttributes: " + authenticatedAttributes +
"\n";
}
out += "\tdigestEncryptionAlgorithmId: " + digestEncryptionAlgorithmId +
"\n";
out += "\tencryptedDigest: " + "\n" +
digestbits + "\n";
if (unauthenticatedAttributes != null) {
out += "\tunauthenticatedAttributes: " +
unauthenticatedAttributes + "\n";
}
return out;
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/provider/ 0000775 0000000 0000000 00000000000 14565430767 0026247 5 ustar 00root root 0000000 0000000 jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/provider/CMS.java 0000664 0000000 0000000 00000003241 14565430767 0027534 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.provider;
import java.security.AccessController;
import java.security.Provider;
/**
* The CMS Security Provider.
*/
public final class CMS extends Provider {
/**
*
*/
private static final long serialVersionUID = 1065207998900104219L;
private static final String INFO = "CMS [X.509 certificates]";
public CMS() {
/* We are the CMS provider */
super("CMS", 1.0, INFO);
AccessController.doPrivileged(new java.security.PrivilegedAction<>() {
@Override
public Object run() {
/*
* Certificates
*/
put("CertificateFactory.X.509", "org.mozilla.jss.netscape.security.provider.X509CertificateFactory");
put("Alg.Alias.CertificateFactory.X.509", "X.509");
return null;
}
});
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/provider/DSAKeyFactory.java 0000664 0000000 0000000 00000022103 14565430767 0031520 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.provider;
import java.security.InvalidKeyException;
import java.security.Key;
import java.security.KeyFactorySpi;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.interfaces.DSAParams;
import java.security.spec.DSAPrivateKeySpec;
import java.security.spec.DSAPublicKeySpec;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.KeySpec;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
/**
* This class implements the DSA key factory of the Sun provider.
*
* @author Jan Luehe
*
* @version 1.8, 97/12/10
*
* @since JDK1.2
*/
public class DSAKeyFactory extends KeyFactorySpi {
/**
* Generates a public key object from the provided key specification
* (key material).
*
* @param keySpec the specification (key material) of the public key
*
* @return the public key
*
* @exception InvalidKeySpecException if the given key specification
* is inappropriate for this key factory to produce a public key.
*/
@Override
protected PublicKey engineGeneratePublic(KeySpec keySpec)
throws InvalidKeySpecException {
try {
if (keySpec instanceof DSAPublicKeySpec) {
DSAPublicKeySpec dsaPubKeySpec = (DSAPublicKeySpec) keySpec;
return new DSAPublicKey(dsaPubKeySpec.getY(),
dsaPubKeySpec.getP(),
dsaPubKeySpec.getQ(),
dsaPubKeySpec.getG());
} else if (keySpec instanceof X509EncodedKeySpec) {
return new DSAPublicKey(((X509EncodedKeySpec) keySpec).getEncoded());
} else {
throw new InvalidKeySpecException("Inappropriate key specification");
}
} catch (InvalidKeyException e) {
throw new InvalidKeySpecException("Inappropriate key specification: " + e.getMessage());
}
}
/**
* Generates a private key object from the provided key specification
* (key material).
*
* @param keySpec the specification (key material) of the private key
*
* @return the private key
*
* @exception InvalidKeySpecException if the given key specification
* is inappropriate for this key factory to produce a private key.
*/
@Override
protected PrivateKey engineGeneratePrivate(KeySpec keySpec)
throws InvalidKeySpecException {
try {
if (keySpec instanceof DSAPrivateKeySpec) {
DSAPrivateKeySpec dsaPrivKeySpec = (DSAPrivateKeySpec) keySpec;
return new DSAPrivateKey(dsaPrivKeySpec.getX(),
dsaPrivKeySpec.getP(),
dsaPrivKeySpec.getQ(),
dsaPrivKeySpec.getG());
} else if (keySpec instanceof PKCS8EncodedKeySpec) {
return new DSAPrivateKey(((PKCS8EncodedKeySpec) keySpec).getEncoded());
} else {
throw new InvalidKeySpecException("Inappropriate key specification");
}
} catch (InvalidKeyException e) {
throw new InvalidKeySpecException("Inappropriate key specification: " + e.getMessage());
}
}
/**
* Returns a specification (key material) of the given key object
* in the requested format.
*
* @param key the key
*
* @param keySpec the requested format in which the key material shall be
* returned
*
* @return the underlying key specification (key material) in the
* requested format
*
* @exception InvalidKeySpecException if the requested key specification is
* inappropriate for the given key, or the given key cannot be processed
* (e.g., the given key has an unrecognized algorithm or format).
*/
@Override
@SuppressWarnings("unchecked")
protected T engineGetKeySpec(Key key, Class keySpec)
throws InvalidKeySpecException {
DSAParams params;
try {
if (key instanceof java.security.interfaces.DSAPublicKey) {
// Determine valid key specs
Class> dsaPubKeySpec = Class.forName
("java.security.spec.DSAPublicKeySpec");
Class> x509KeySpec = Class.forName
("java.security.spec.X509EncodedKeySpec");
if (dsaPubKeySpec.isAssignableFrom(keySpec)) {
java.security.interfaces.DSAPublicKey dsaPubKey = (java.security.interfaces.DSAPublicKey) key;
params = dsaPubKey.getParams();
return (T) new DSAPublicKeySpec(dsaPubKey.getY(),
params.getP(),
params.getQ(),
params.getG());
} else if (x509KeySpec.isAssignableFrom(keySpec)) {
return (T) new X509EncodedKeySpec(key.getEncoded());
} else {
throw new InvalidKeySpecException("Inappropriate key specification");
}
} else if (key instanceof java.security.interfaces.DSAPrivateKey) {
// Determine valid key specs
Class> dsaPrivKeySpec = Class.forName
("java.security.spec.DSAPrivateKeySpec");
Class> pkcs8KeySpec = Class.forName
("java.security.spec.PKCS8EncodedKeySpec");
if (dsaPrivKeySpec.isAssignableFrom(keySpec)) {
java.security.interfaces.DSAPrivateKey dsaPrivKey = (java.security.interfaces.DSAPrivateKey) key;
params = dsaPrivKey.getParams();
return (T) new DSAPrivateKeySpec(dsaPrivKey.getX(),
params.getP(),
params.getQ(),
params.getG());
} else if (pkcs8KeySpec.isAssignableFrom(keySpec)) {
return (T) new PKCS8EncodedKeySpec(key.getEncoded());
} else {
throw new InvalidKeySpecException("Inappropriate key specification");
}
} else {
throw new InvalidKeySpecException("Inappropriate key type");
}
} catch (ClassNotFoundException e) {
throw new InvalidKeySpecException("Unsupported key specification: " + e.getMessage());
}
}
/**
* Translates a key object, whose provider may be unknown or potentially
* untrusted, into a corresponding key object of this key factory.
*
* @param key the key whose provider is unknown or untrusted
*
* @return the translated key
*
* @exception InvalidKeyException if the given key cannot be processed by
* this key factory.
*/
@Override
protected Key engineTranslateKey(Key key) throws InvalidKeyException {
try {
if (key instanceof java.security.interfaces.DSAPublicKey) {
// Check if key originates from this factory
if (key instanceof org.mozilla.jss.netscape.security.provider.DSAPublicKey) {
return key;
}
// Convert key to spec
DSAPublicKeySpec dsaPubKeySpec = engineGetKeySpec(key, DSAPublicKeySpec.class);
// Create key from spec, and return it
return engineGeneratePublic(dsaPubKeySpec);
} else if (key instanceof java.security.interfaces.DSAPrivateKey) {
// Check if key originates from this factory
if (key instanceof org.mozilla.jss.netscape.security.provider.DSAPrivateKey) {
return key;
}
// Convert key to spec
DSAPrivateKeySpec dsaPrivKeySpec = engineGetKeySpec(key, DSAPrivateKeySpec.class);
// Create key from spec, and return it
return engineGeneratePrivate(dsaPrivKeySpec);
} else {
throw new InvalidKeyException("Wrong algorithm type");
}
} catch (InvalidKeySpecException e) {
throw new InvalidKeyException("Cannot translate key: "
+ e.getMessage());
}
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/provider/DSAParameters.java 0000664 0000000 0000000 00000011176 14565430767 0031553 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.provider;
import java.io.IOException;
import java.math.BigInteger;
import java.security.AlgorithmParametersSpi;
import java.security.spec.AlgorithmParameterSpec;
import java.security.spec.DSAParameterSpec;
import java.security.spec.InvalidParameterSpecException;
import org.mozilla.jss.netscape.security.util.BigInt;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
/**
* This class implements the parameter set used by the
* Digital Signature Algorithm as specified in the FIPS 186
* standard.
*
* @author Jan Luehe
*
* @version 1.8, 97/12/10
*
* @since JDK1.2
*/
public class DSAParameters extends AlgorithmParametersSpi {
// the prime (p)
protected BigInteger p;
// the sub-prime (q)
protected BigInteger q;
// the base (g)
protected BigInteger g;
@Override
protected void engineInit(AlgorithmParameterSpec paramSpec)
throws InvalidParameterSpecException {
if (!(paramSpec instanceof DSAParameterSpec)) {
throw new InvalidParameterSpecException("Inappropriate parameter specification");
}
this.p = ((DSAParameterSpec) paramSpec).getP();
this.q = ((DSAParameterSpec) paramSpec).getQ();
this.g = ((DSAParameterSpec) paramSpec).getG();
}
@Override
protected void engineInit(byte[] params) throws IOException {
DerValue encodedParams = new DerValue(params);
if (encodedParams.tag != DerValue.tag_Sequence) {
throw new IOException("DSA params parsing error");
}
encodedParams.data.reset();
this.p = encodedParams.data.getInteger().toBigInteger();
this.q = encodedParams.data.getInteger().toBigInteger();
this.g = encodedParams.data.getInteger().toBigInteger();
if (encodedParams.data.available() != 0) {
throw new IOException("encoded params have " +
encodedParams.data.available() +
" extra bytes");
}
}
@Override
protected void engineInit(byte[] params, String decodingMethod)
throws IOException {
engineInit(params);
}
@Override
@SuppressWarnings("unchecked")
protected T engineGetParameterSpec(Class paramSpec)
throws InvalidParameterSpecException {
try {
Class> dsaParamSpec = Class.forName
("java.security.spec.DSAParameterSpec");
if (dsaParamSpec.isAssignableFrom(paramSpec)) {
return (T) new DSAParameterSpec(this.p, this.q, this.g);
} else {
throw new InvalidParameterSpecException("Inappropriate parameter Specification");
}
} catch (ClassNotFoundException e) {
throw new InvalidParameterSpecException("Unsupported parameter specification: " + e.getMessage());
}
}
@Override
protected byte[] engineGetEncoded() throws IOException {
try (DerOutputStream out = new DerOutputStream()) {
DerOutputStream bytes = new DerOutputStream();
bytes.putInteger(new BigInt(p.toByteArray()));
bytes.putInteger(new BigInt(q.toByteArray()));
bytes.putInteger(new BigInt(g.toByteArray()));
out.write(DerValue.tag_Sequence, bytes);
return out.toByteArray();
}
}
@Override
protected byte[] engineGetEncoded(String encodingMethod)
throws IOException {
return engineGetEncoded();
}
/*
* Returns a formatted string describing the parameters.
*/
@Override
protected String engineToString() {
return "\n\tp: " + new BigInt(p).toString()
+ "\n\tq: " + new BigInt(q).toString()
+ "\n\tg: " + new BigInt(g).toString()
+ "\n";
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/provider/DSAPrivateKey.java 0000664 0000000 0000000 00000011701 14565430767 0031525 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.provider;
import java.io.IOException;
import java.math.BigInteger;
import java.security.AlgorithmParameters;
import java.security.InvalidKeyException;
import java.security.interfaces.DSAParams;
import java.security.spec.DSAParameterSpec;
import java.security.spec.InvalidParameterSpecException;
import org.mozilla.jss.netscape.security.pkcs.PKCS8Key;
import org.mozilla.jss.netscape.security.util.DerInputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
import org.mozilla.jss.netscape.security.x509.AlgIdDSA;
/**
* A PKCS#8 private key for the Digital Signature Algorithm.
*
* @author Benjamin Renaud
*
* @version 1.47, 97/12/10
*
* @see DSAPublicKey
* @see AlgIdDSA
*/
public final class DSAPrivateKey extends PKCS8Key
implements java.security.interfaces.DSAPrivateKey {
/** use serialVersionUID from JDK 1.1. for interoperability */
private static final long serialVersionUID = -3244453684193605938L;
/* the private key */
private BigInteger x;
/*
* Keep this constructor for backwards compatibility with JDK1.1.
*/
public DSAPrivateKey() {
}
/**
* Make a DSA private key out of a private key and three parameters.
*/
public DSAPrivateKey(BigInteger x, BigInteger p,
BigInteger q, BigInteger g)
throws InvalidKeyException {
this.x = x;
algid = new AlgIdDSA(p, q, g);
try {
key = new DerValue(DerValue.tag_Integer,
x.toByteArray()).toByteArray();
encode();
} catch (IOException e) {
throw new InvalidKeyException("could not DER encode x: " +
e.getMessage());
}
}
/**
* Make a DSA private key from its DER encoding (PKCS #8).
*/
public DSAPrivateKey(byte[] encoded) throws InvalidKeyException {
clearOldKey();
decode(encoded);
}
/**
* Returns the DSA parameters associated with this key, or null if the
* parameters could not be parsed.
*/
@Override
public DSAParams getParams() {
try {
if (algid instanceof DSAParams) {
return (DSAParams) algid;
} else {
AlgorithmParameters algParams = algid.getParameters();
if (algParams == null) {
return null;
}
return algParams.getParameterSpec(DSAParameterSpec.class);
}
} catch (InvalidParameterSpecException e) {
return null;
}
}
/**
* Get the raw private key, x, without the parameters.
*
*/
@Override
public BigInteger getX() {
return x;
}
private void clearOldKey() {
int i;
if (this.encodedKey != null) {
for (i = 0; i < this.encodedKey.length; i++) {
this.encodedKey[i] = (byte) 0x00;
}
}
if (this.key != null) {
for (i = 0; i < this.key.length; i++) {
this.key[i] = (byte) 0x00;
}
}
}
@Override
public String toString() {
return "Sun DSA Private Key \nparameters:" + algid + "\nx: " +
x.toString(16) + "\n";
}
@Override
protected void parseKeyBits() throws InvalidKeyException {
DerInputStream in = new DerInputStream(key);
try {
x = in.getInteger().toBigInteger();
} catch (IOException e) {
throw new InvalidKeyException(e.getMessage());
}
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((x == null) ? 0 : x.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
DSAPrivateKey other = (DSAPrivateKey) obj;
if (x == null) {
if (other.x != null)
return false;
} else if (!x.equals(other.x))
return false;
return true;
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/provider/DSAPublicKey.java 0000664 0000000 0000000 00000011410 14565430767 0031326 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.provider;
import java.io.IOException;
import java.math.BigInteger;
import java.security.AlgorithmParameters;
import java.security.InvalidKeyException;
import java.security.interfaces.DSAParams;
import java.security.spec.DSAParameterSpec;
import java.security.spec.InvalidParameterSpecException;
import org.mozilla.jss.netscape.security.util.BigInt;
import org.mozilla.jss.netscape.security.util.DerInputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
import org.mozilla.jss.netscape.security.x509.AlgIdDSA;
import org.mozilla.jss.netscape.security.x509.X509Key;
/**
* An X.509 public key for the Digital Signature Algorithm.
*
* @author Benjamin Renaud
*
* @version 1.52, 97/12/10
*
* @see DSAPrivateKey
* @see AlgIdDSA
*/
public final class DSAPublicKey extends X509Key
implements java.security.interfaces.DSAPublicKey {
/** use serialVersionUID from JDK 1.1. for interoperability */
private static final long serialVersionUID = -2994193307391104133L;
/* the public key */
private BigInteger y;
/*
* Keep this constructor for backwards compatibility with JDK1.1.
*/
public DSAPublicKey() {
}
/**
* Make a DSA public key out of a public key and three parameters.
*/
public DSAPublicKey(BigInteger y, BigInteger p, BigInteger q,
BigInteger g)
throws InvalidKeyException {
this.y = y;
algid = new AlgIdDSA(p, q, g);
try {
key = new DerValue(DerValue.tag_Integer,
y.toByteArray()).toByteArray();
encode();
} catch (IOException e) {
throw new InvalidKeyException("could not DER encode y: " +
e.getMessage());
}
}
/**
* Make a DSA public key from its DER encoding (X.509).
*/
public DSAPublicKey(byte[] encoded) throws InvalidKeyException {
decode(encoded);
}
/**
* Returns the DSA parameters associated with this key, or null if the
* parameters could not be parsed.
*/
@Override
public DSAParams getParams() {
try {
if (algid instanceof DSAParams) {
return (DSAParams) algid;
} else {
DSAParameterSpec paramSpec;
AlgorithmParameters algParams = algid.getParameters();
if (algParams == null) {
return null;
}
paramSpec = algParams.getParameterSpec
(DSAParameterSpec.class);
return paramSpec;
}
} catch (InvalidParameterSpecException e) {
return null;
}
}
/**
* Get the raw public value, y, without the parameters.
*
*/
@Override
public BigInteger getY() {
return y;
}
@Override
public String toString() {
return "Sun DSA Public Key\n Parameters:" + algid
+ "\n y:\n" + (new BigInt(y)).toString() + "\n";
}
@Override
protected void parseKeyBits() throws InvalidKeyException {
try {
DerInputStream in = new DerInputStream(key);
y = in.getInteger().toBigInteger();
} catch (IOException e) {
throw new InvalidKeyException("Invalid key: y value\n" +
e.getMessage());
}
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((y == null) ? 0 : y.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
DSAPublicKey other = (DSAPublicKey) obj;
if (y == null) {
if (other.y != null)
return false;
} else if (!y.equals(other.y))
return false;
return true;
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/provider/RSAPublicKey.java 0000664 0000000 0000000 00000013561 14565430767 0031355 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.provider;
import java.io.IOException;
import java.security.InvalidKeyException;
import org.mozilla.jss.netscape.security.util.BigInt;
import org.mozilla.jss.netscape.security.util.DerInputStream;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
import org.mozilla.jss.netscape.security.util.ObjectIdentifier;
import org.mozilla.jss.netscape.security.x509.AlgorithmId;
import org.mozilla.jss.netscape.security.x509.X509Key;
/**
* An X.509 public key for the RSA Algorithm.
*
* @author galperin
*
* @version $Revision$, $Date$
*
*/
public final class RSAPublicKey extends X509Key {
/* XXX This currently understands only PKCS#1 RSA Encryption OID
and parameter format
Later we may consider adding X509v3 OID for RSA keys. Besides
different OID it also has a parameter equal to modulus size
in bits (redundant!)
*/
/**
*
*/
private static final long serialVersionUID = 7764823589128565374L;
private static final ObjectIdentifier ALGORITHM_OID =
AlgorithmId.RSAEncryption_oid;
private BigInt modulus;
private BigInt publicExponent;
/*
* Keep this constructor for backwards compatibility with JDK1.1.
*/
public RSAPublicKey() {
}
/**
* Make a RSA public key out of a public exponent and modulus
*/
public RSAPublicKey(BigInt modulus, BigInt publicExponent)
throws InvalidKeyException {
this.modulus = modulus;
this.publicExponent = publicExponent;
this.algid = new AlgorithmId(ALGORITHM_OID);
try (DerOutputStream out = new DerOutputStream()) {
out.putInteger(modulus);
out.putInteger(publicExponent);
key = (new DerValue(DerValue.tag_Sequence,
out.toByteArray())).toByteArray();
encode();
} catch (IOException ex) {
throw new InvalidKeyException("could not DER encode : " +
ex.getMessage());
}
}
/**
* Make a RSA public key from its DER encoding (X.509).
*/
public RSAPublicKey(byte[] encoded) throws InvalidKeyException {
decode(encoded);
}
/**
* Get key size as number of bits in modulus
* (Always rounded up to a multiple of 8)
*
*/
public int getKeySize() {
return this.modulus.byteLength() * 8;
}
/**
* Get the raw public exponent
*
*/
public BigInt getPublicExponent() {
return this.publicExponent;
}
/**
* Get the raw modulus
*
*/
public BigInt getModulus() {
return this.modulus;
}
@Override
public String toString() {
return "RSA Public Key\n Algorithm: " + algid
+ "\n modulus:\n" + this.modulus.toString() + "\n"
+ "\n publicExponent:\n" + this.publicExponent.toString()
+ "\n";
}
@Override
protected void parseKeyBits() throws InvalidKeyException {
if (!this.algid.getOID().equals(ALGORITHM_OID) &&
!this.algid.getOID().equals(AlgorithmId.RSA_oid)) {
throw new InvalidKeyException("Key algorithm OID is not RSA");
}
try {
DerValue val = new DerValue(key);
if (val.tag != DerValue.tag_Sequence) {
throw new InvalidKeyException("Invalid RSA public key format:" +
" must be a SEQUENCE");
}
DerInputStream in = val.data;
this.modulus = in.getInteger();
this.publicExponent = in.getInteger();
} catch (IOException e) {
throw new InvalidKeyException("Invalid RSA public key: " +
e.getMessage());
}
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((modulus == null) ? 0 : modulus.hashCode());
result = prime * result + ((publicExponent == null) ? 0 : publicExponent.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
RSAPublicKey other = (RSAPublicKey) obj;
if (modulus == null) {
if (other.modulus != null)
return false;
} else if (!modulus.equals(other.modulus))
return false;
if (publicExponent == null) {
if (other.publicExponent != null)
return false;
} else if (!publicExponent.equals(other.publicExponent))
return false;
return true;
}
public boolean bigIntEquals(BigInt x, BigInt y) {
if (x == null) {
if (y != null) {
return false;
}
} else {
if (!x.equals(y)) {
return false;
}
}
return true;
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/provider/Sun.java 0000664 0000000 0000000 00000006011 14565430767 0027655 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.provider;
import java.security.Provider;
/**
* The SUN Security Provider.
*
* @author Benjamin Renaud
*
* @version 1.24, 97/12/10
*/
/**
* Defines the SUN provider.
*
* Algorithm supported, and their names:
*
* - SHA-1 is the message digest scheme decribed FIPS 180-1.
* Aliases for SHA-1 are SHA.
*
* - DSA is the signature scheme described in FIPS 186. (SHA used in
* DSA is SHA-1: FIPS 186 with Change No 1.) Aliases for DSA are
* SHA/DSA, SHA-1/DSA, SHA1/DSA, DSS and the object identifier
* strings "OID.1.3.14.3.2.13", "OID.1.3.14.3.2.27" and
* "OID.1.2.840.10040.4.3".
*
* - DSA is the key generation scheme as described in FIPS 186.
* Aliases for DSA include the OID strings "OID.1.3.14.3.2.12"
* and "OID.1.2.840.10040.4.1".
*
* - MD5 is the message digest scheme described in RFC 1321.
* There are no aliases for MD5.
*
* Notes: The name of algorithm described in FIPS-180 is SHA-0, and is
* not supported by the SUN provider.)
*/
public final class Sun extends Provider {
/**
*
*/
private static final long serialVersionUID = 9134942296334703727L;
private static String info = "SUN Security Provider v1.0, " +
"DSA signing and key generation, SHA-1 and MD5 message digests.";
public Sun() {
/* We are the SUN provider */
super("SUN", 1.0, info);
try {
// AccessController.beginPrivileged();
// the following are not according to our formal spec but
// are still supported
put("Alg.Alias.KeyPairGenerator.1.3.14.3.2.12", "DSA");
put("Alg.Alias.KeyPairGenerator.1.2.840.10040.4.1", "DSA");
/*
* Algorithm Parameter engines
*/
put("AlgorithmParameters.DSA",
"org.mozilla.jss.netscape.security.provider.DSAParameters");
put("Alg.Alias.AlgorithmParameters.1.3.14.3.2.12", "DSA");
put("Alg.Alias.AlgorithmParameters.1.2.840.10040.4.1", "DSA");
/*
* Key factories
*/
put("KeyFactory.DSA", "org.mozilla.jss.netscape.security.provider.DSAKeyFactory");
} finally {
// AccessController.endPrivileged();
}
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/provider/X509CertificateFactory.java 0000664 0000000 0000000 00000004140 14565430767 0033251 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.provider;
import java.io.InputStream;
import java.security.cert.CRL;
import java.security.cert.CRLException;
import java.security.cert.Certificate;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactorySpi;
import java.util.Collection;
import org.mozilla.jss.netscape.security.x509.X509CRLImpl;
import org.mozilla.jss.netscape.security.x509.X509CertImpl;
import org.mozilla.jss.netscape.security.x509.X509ExtensionException;
public class X509CertificateFactory extends CertificateFactorySpi {
@Override
public Certificate engineGenerateCertificate(InputStream inStream)
throws CertificateException {
return new X509CertImpl(inStream);
}
@Override
public Collection engineGenerateCertificates(InputStream inStream)
throws CertificateException {
return null;
}
@Override
public CRL engineGenerateCRL(InputStream inStream)
throws CRLException {
X509CRLImpl crl = null;
try {
crl = new X509CRLImpl(inStream);
} catch (X509ExtensionException e) {
;
}
return crl;
}
@Override
public Collection engineGenerateCRLs(InputStream inStream)
throws CRLException {
return null;
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/util/ 0000775 0000000 0000000 00000000000 14565430767 0025372 5 ustar 00root root 0000000 0000000 jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/util/ASN1CharStrConvMap.java 0000664 0000000 0000000 00000012253 14565430767 0031515 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.util;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
* Maps a ASN.1 character string type to a charset encoder and decoder.
* The converter is used to convert a DerValue of a ASN.1 character string type
* from bytes to unicode characters and vice versa.
*
*
* A global default ASN1CharStrConvMap is created when the class is initialized. The global default map is extensible.
*
* @author Lily Hsiao
* @author Slava Galperin
*
*/
public class ASN1CharStrConvMap {
// public constructors
/**
* Constructs a ASN1CharStrConvMap.
*/
public ASN1CharStrConvMap() {
}
/**
* Get an encoder for the specified DER tag.
*
* @param tag A DER tag of a ASN.1 character string type,
* for example DerValue.tag_PrintableString.
*
* @return An encoder for the DER tag.
*/
public CharsetEncoder getEncoder(byte tag) {
Charset charset = charsets.get(tag);
if (charset == null)
return null;
return charset.newEncoder();
}
/**
* Get a decoder for the given DER tag.
*
* @param tag A DER tag of a ASN.1 character string type,
* for example DerValue.tag_PrintableString.
*
* @return A decoder for the DER tag.
*/
public CharsetDecoder getDecoder(byte tag) {
Charset charset = charsets.get(tag);
if (charset == null)
return null;
return charset.newDecoder();
}
/**
* Add a tag-charset entry in the map.
*
* @param tag A DER tag of a ASN.1 character string type,
* ex. DerValue.tag_IA5String
* @param charset A charset for the tag.
*/
public void addEntry(byte tag, Charset charset) {
Charset currentCharset = charsets.get(tag);
if (currentCharset != null) {
if (currentCharset != charset) {
throw new IllegalArgumentException(
"a DER tag to converter entry already exists.");
}
return;
}
charsets.put(tag, charset);
}
/**
* Get an iterator of all tags in the map.
*
* @return An Iterator of DER tags in the map as Bytes.
*/
public Iterator getTags() {
return charsets.keySet().iterator();
}
// static public methods.
/**
* Get the global ASN1CharStrConvMap.
*
* @return The global default ASN1CharStrConvMap.
*/
static public ASN1CharStrConvMap getDefault() {
return defaultMap;
}
/**
* Set the global default ASN1CharStrConvMap.
*
* @param newDefault The new default ASN1CharStrConvMap.
*/
static public void setDefault(ASN1CharStrConvMap newDefault) {
if (newDefault == null)
throw new IllegalArgumentException(
"Cannot set a null default Der Tag Converter map");
defaultMap = newDefault;
}
// private methods and variables.
private Map charsets = new HashMap<>();
private static ASN1CharStrConvMap defaultMap;
/**
* Create the default converter map on initialization
*/
static {
ASN1CharsetProvider provider = new ASN1CharsetProvider();
defaultMap = new ASN1CharStrConvMap();
defaultMap.addEntry(DerValue.tag_PrintableString,
provider.charsetForName("ASN.1-Printable"));
defaultMap.addEntry(DerValue.tag_VisibleString,
provider.charsetForName("ASN.1-Printable"));
defaultMap.addEntry(DerValue.tag_IA5String,
provider.charsetForName("ASN.1-IA5"));
defaultMap.addEntry(DerValue.tag_BMPString,
Charset.forName("UnicodeBig"));
defaultMap.addEntry(DerValue.tag_UniversalString,
provider.charsetForName("ASN.1-Universal"));
// XXX this is an oversimplified implementation of T.61 strings, it
// doesn't handle all cases
defaultMap.addEntry(DerValue.tag_T61String,
Charset.forName("ISO-8859-1"));
// UTF8String added to ASN.1 in 1998
defaultMap.addEntry(DerValue.tag_UTF8String,
Charset.forName("UTF-8"));
defaultMap.addEntry(DerValue.tag_GeneralString,
Charset.forName("UTF-8"));
};
};
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/util/ASN1CharsetProvider.java 0000664 0000000 0000000 00000001450 14565430767 0031764 0 ustar 00root root 0000000 0000000 package org.mozilla.jss.netscape.security.util;
import java.nio.charset.Charset;
import java.nio.charset.spi.CharsetProvider;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
public class ASN1CharsetProvider extends CharsetProvider {
protected Map charsets = new HashMap<>();
public ASN1CharsetProvider() {
addCharset(new PrintableCharset());
addCharset(new IA5Charset());
addCharset(new UniversalCharset());
}
@Override
public Iterator charsets() {
return charsets.values().iterator();
}
@Override
public Charset charsetForName(String charsetName) {
return charsets.get(charsetName);
}
public void addCharset(Charset cs) {
charsets.put(cs.name(), cs);
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/util/BigInt.java 0000664 0000000 0000000 00000015376 14565430767 0027425 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.util;
import java.io.Serializable;
import java.math.BigInteger;
import java.util.Arrays;
/**
* A low-overhead arbitrary-precision unsigned integer.
* This is intended for use with ASN.1 parsing, and printing of
* such parsed values. Convert to "BigInteger" if you need to do
* arbitrary precision arithmetic, rather than just represent
* the number as a wrapped array of bytes.
*
*
* NOTE: This class may eventually disappear, to
* be supplanted by big-endian byte arrays which hold both signed
* and unsigned arbitrary-precision integers.
*
* @version 1.23
* @author David Brownell
*/
public final class BigInt implements Serializable {
private static final long serialVersionUID = 705094142021888265L;
// Big endian -- MSB first.
private byte[] places;
/**
* Constructs a "Big" integer from a set of (big-endian) bytes.
* Leading zeroes should be stripped off.
*
* @param data a sequence of bytes, most significant bytes/digits
* first. CONSUMED.
*/
public BigInt(byte[] data) {
places = data.clone();
}
/**
* Constructs a "Big" integer from a "BigInteger", which must be
* positive (or zero) in value.
*/
public BigInt(BigInteger i) {
byte[] temp = i.toByteArray();
if ((temp[0] & 0x80) != 0)
throw new IllegalArgumentException("negative BigInteger");
// XXX we assume exactly _one_ sign byte is used...
if (temp[0] != 0)
places = temp;
else {
// Note that if i = new BigInteger("0"),
// i.toByteArray() contains only 1 zero.
if (temp.length == 1) {
places = new byte[1];
places[0] = (byte) 0;
} else {
places = new byte[temp.length - 1];
for (int j = 1; j < temp.length; j++)
places[j - 1] = temp[j];
}
}
}
/**
* Constructs a "Big" integer from a normal Java integer.
*
* @param i the java primitive integer
*/
public BigInt(int i) {
if (i < (1 << 8)) {
places = new byte[1];
places[0] = (byte) i;
} else if (i < (1 << 16)) {
places = new byte[2];
places[0] = (byte) (i >> 8);
places[1] = (byte) i;
} else if (i < (1 << 24)) {
places = new byte[3];
places[0] = (byte) (i >> 16);
places[1] = (byte) (i >> 8);
places[2] = (byte) i;
} else {
places = new byte[4];
places[0] = (byte) (i >> 24);
places[1] = (byte) (i >> 16);
places[2] = (byte) (i >> 8);
places[3] = (byte) i;
}
}
/**
* Converts the "big" integer to a java primitive integer.
*
* @exception NumberFormatException if 32 bits is insufficient.
*/
public int toInt() {
if (places.length > 4)
throw new NumberFormatException("BigInt.toInt, too big");
int retval = 0, i = 0;
for (; i < places.length; i++)
retval = (retval << 8) + (places[i] & 0xff);
return retval;
}
/**
* Returns a hexadecimal printed representation. The value is
* formatted to fit on lines of at least 75 characters, with
* embedded newlines. Words are separated for readability,
* with eight words (32 bytes) per line.
*/
@Override
public String toString() {
return hexify();
}
/**
* Returns a BigInteger value which supports many arithmetic
* operations. Assumes negative values will never occur.
*/
public BigInteger toBigInteger() {
return new BigInteger(1, places);
}
/**
* Returns the length of the data as a byte array.
*/
public int byteLength() {
return places.length;
}
/**
* Returns the data as a byte array. The most significant bit
* of the array is bit zero (as in java.math.BigInteger
).
*/
public byte[] toByteArray() {
if (places.length == 0) {
byte zero[] = new byte[1];
zero[0] = (byte) 0;
return zero;
} else {
return places.clone();
}
}
private static final String digits = "0123456789abcdef";
private String hexify() {
if (places.length == 0)
return " 0 ";
StringBuffer buf = new StringBuffer(places.length * 2);
buf.append(" "); // four spaces
for (int i = 0; i < places.length; i++) {
buf.append(digits.charAt((places[i] >> 4) & 0x0f));
buf.append(digits.charAt(places[i] & 0x0f));
if (((i + 1) % 32) == 0) {
if ((i + 1) != places.length)
buf.append("\n "); // line after four words
} else if (((i + 1) % 4) == 0)
buf.append(' '); // space between words
}
return buf.toString();
}
/**
* Returns true iff the parameter is a numerically equivalent
* BigInt.
*
* @param other the object being compared with this one.
*/
@Override
public boolean equals(Object other) {
if (other instanceof BigInt)
return equals((BigInt) other);
return false;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + Arrays.hashCode(places);
return result;
}
/**
* Returns true iff the parameter is numerically equivalent.
*
* @param other the BigInt being compared with this one.
*/
public boolean equals(BigInt other) {
if (this == other)
return true;
byte[] otherPlaces = other.toByteArray();
if (places.length != otherPlaces.length)
return false;
for (int i = 0; i < places.length; i++)
if (places[i] != otherPlaces[i])
return false;
return true;
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/util/BitArray.java 0000664 0000000 0000000 00000017466 14565430767 0027770 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.util;
import java.io.ByteArrayOutputStream;
/**
* A packed array of booleans.
*
* @author Joshua Bloch
* @author Douglas Hoover
* @version 1.2 97/12/10
*/
public class BitArray {
private byte[] repn;
private int length;
private static final int BITS_PER_UNIT = 8;
private static int subscript(int idx) {
return idx / BITS_PER_UNIT;
}
private static int position(int idx) { // bits big-endian in each unit
return 1 << (BITS_PER_UNIT - 1 - (idx % BITS_PER_UNIT));
}
/**
* Creates a BitArray of the specified size, initialized to zeros.
*/
public BitArray(int length) throws IllegalArgumentException {
if (length < 0) {
throw new IllegalArgumentException("Negative length for BitArray");
}
this.length = length;
repn = new byte[(length + BITS_PER_UNIT - 1) / BITS_PER_UNIT];
}
/**
* Creates a BitArray of the specified size, initialized from the
* specified byte array. The most significant bit of a[0] gets
* index zero in the BitArray. The array a must be large enough
* to specify a value for every bit in the BitArray. In other words,
* {@code 8*a.length >= length}.
*/
public BitArray(int length, byte[] a) throws IllegalArgumentException {
if (length < 0) {
throw new IllegalArgumentException("Negative length for BitArray");
}
if (a.length * BITS_PER_UNIT < length) {
throw new IllegalArgumentException("Byte array too short to represent " +
"bit array of given length");
}
this.length = length;
int repLength = ((length + BITS_PER_UNIT - 1) / BITS_PER_UNIT);
int unusedBits = repLength * BITS_PER_UNIT - length;
byte bitMask = (byte) (0xFF << unusedBits);
/*
normalize the representation:
1. discard extra bytes
2. zero out extra bits in the last byte
*/
repn = new byte[repLength];
System.arraycopy(a, 0, repn, 0, repLength);
if (repn.length > 0)
repn[repn.length - 1] = (byte) (repn[repn.length - 1] & bitMask);
}
/**
* Create a BitArray whose bits are those of the given array
* of Booleans.
*/
public BitArray(boolean[] bits) {
length = bits.length;
repn = new byte[(length + 7) / 8];
for (int i = 0; i < length; i++) {
set(i, bits[i]);
}
}
/**
* Copy constructor (for cloning).
*/
private BitArray(BitArray ba) {
length = ba.length;
repn = ba.repn.clone();
}
/**
* Returns the indexed bit in this BitArray.
*/
public boolean get(int index) throws ArrayIndexOutOfBoundsException {
if (index < 0 || index >= length) {
throw new ArrayIndexOutOfBoundsException(Integer.toString(index));
}
return (repn[subscript(index)] & position(index)) != 0;
}
/**
* Sets the indexed bit in this BitArray.
*/
public void set(int index, boolean value)
throws ArrayIndexOutOfBoundsException {
if (index < 0 || index >= length) {
throw new ArrayIndexOutOfBoundsException(Integer.toString(index));
}
int idx = subscript(index);
int bit = position(index);
if (value) {
repn[idx] |= bit;
} else {
repn[idx] &= ~bit;
}
}
/**
* Returns the length of this BitArray.
*/
public int length() {
return length;
}
/**
* Returns a Byte array containing the contents of this BitArray.
* The bit stored at index zero in this BitArray will be copied
* into the most significant bit of the zeroth element of the
* returned byte array. The last byte of the returned byte array
* will be contain zeros in any bits that do not have corresponding
* bits in the BitArray. (This matters only if the BitArray's size
* is not a multiple of 8.)
*/
public byte[] toByteArray() {
return repn.clone();
}
@Override
public boolean equals(Object obj) {
if (obj == this)
return true;
if (obj == null || !(obj instanceof BitArray))
return false;
BitArray ba = (BitArray) obj;
if (ba.length != length)
return false;
for (int i = 0; i < repn.length; i += 1) {
if (repn[i] != ba.repn[i])
return false;
}
return true;
}
/**
* Return a boolean array with the same bit values a this BitArray.
*/
public boolean[] toBooleanArray() {
boolean[] bits = new boolean[length];
for (int i = 0; i < length; i++) {
bits[i] = get(i);
}
return bits;
}
/**
* Returns a hash code value for this bit array.
*
* @return a hash code value for this bit array.
*/
@Override
public int hashCode() {
int hashCode = 0;
for (int i = 0; i < repn.length; i++)
hashCode = 31 * hashCode + repn[i];
return hashCode ^ length;
}
@Override
public Object clone() {
return new BitArray(this);
}
private static final byte[][] NYBBLE = {
{ (byte) '0', (byte) '0', (byte) '0', (byte) '0' },
{ (byte) '0', (byte) '0', (byte) '0', (byte) '1' },
{ (byte) '0', (byte) '0', (byte) '1', (byte) '0' },
{ (byte) '0', (byte) '0', (byte) '1', (byte) '1' },
{ (byte) '0', (byte) '1', (byte) '0', (byte) '0' },
{ (byte) '0', (byte) '1', (byte) '0', (byte) '1' },
{ (byte) '0', (byte) '1', (byte) '1', (byte) '0' },
{ (byte) '0', (byte) '1', (byte) '1', (byte) '1' },
{ (byte) '1', (byte) '0', (byte) '0', (byte) '0' },
{ (byte) '1', (byte) '0', (byte) '0', (byte) '1' },
{ (byte) '1', (byte) '0', (byte) '1', (byte) '0' },
{ (byte) '1', (byte) '0', (byte) '1', (byte) '1' },
{ (byte) '1', (byte) '1', (byte) '0', (byte) '0' },
{ (byte) '1', (byte) '1', (byte) '0', (byte) '1' },
{ (byte) '1', (byte) '1', (byte) '1', (byte) '0' },
{ (byte) '1', (byte) '1', (byte) '1', (byte) '1' }
};
private static final int BYTES_PER_LINE = 8;
/**
* Returns a string representation of this BitArray.
*/
@Override
public String toString() {
ByteArrayOutputStream out = new ByteArrayOutputStream();
for (int i = 0; i < repn.length - 1; i++) {
out.write(NYBBLE[(repn[i] >> 4) & 0x0F], 0, 4);
out.write(NYBBLE[repn[i] & 0x0F], 0, 4);
if (i % BYTES_PER_LINE == BYTES_PER_LINE - 1) {
out.write('\n');
} else {
out.write(' ');
}
}
// in last byte of repn, use only the valid bits
for (int i = BITS_PER_UNIT * (repn.length - 1); i < length; i++) {
out.write(get(i) ? '1' : '0');
}
return new String(out.toByteArray());
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/util/ByteArrayLexOrder.java 0000664 0000000 0000000 00000004202 14565430767 0031602 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.util;
import java.util.Comparator;
/**
* Compare two byte arrays in lexicographical order.
*
* @version 1.4 97/12/10
* @author D. N. Hoover
*/
public class ByteArrayLexOrder implements Comparator, java.io.Serializable {
private static final long serialVersionUID = 1897537410212918669L;
/**
* Perform lexicographical comparison of two byte arrays,
* regarding each byte as unsigned. That is, compare array entries
* in order until they differ--the array with the smaller entry
* is "smaller". If array entries are
* equal till one array ends, then the longer array is "bigger".
*
* @param bytes1 first byte array to compare.
* @param bytes2 second byte array to compare.
* @return negative number if {@literal bytes1 < bytes2}, 0 if bytes1 == bytes2,
* positive number if {@literal bytes1 > bytes2}.
*/
@Override
public final int compare(byte[] bytes1, byte[] bytes2) {
int diff;
for (int i = 0; i < bytes1.length && i < bytes2.length; i++) {
diff = (bytes1[i] & 0xFF) - (bytes2[i] & 0xFF);
if (diff != 0) {
return diff;
}
}
// if array entries are equal till the first ends, then the
// longer is "bigger"
return bytes1.length - bytes2.length;
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/util/ByteArrayTagOrder.java 0000664 0000000 0000000 00000003312 14565430767 0031566 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.util;
import java.util.Comparator;
public class ByteArrayTagOrder implements Comparator, java.io.Serializable {
private static final long serialVersionUID = -2027007556858126443L;
/**
* Compare two byte arrays, by the order of their tags,
* as defined in ITU-T X.680, sec. 6.4. (First compare
* tag classes, then tag numbers, ignoring the constructivity bit.)
*
* @param bytes1 first byte array to compare.
* @param bytes2 second byte array to compare.
* @return negative number if {@literal bytes1 < bytes2}, 0 if bytes1 == bytes2,
* positive number if {@literal bytes1 > bytes2}.
*/
@Override
public final int compare(byte[] bytes1, byte[] bytes2) {
// tag order is same as byte order ignoring any difference in
// the constructivity bit (0x02)
return (bytes1[0] | 0x20) - (bytes2[0] | 0x20);
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/util/Cert.java 0000664 0000000 0000000 00000027725 14565430767 0027147 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.util;
import java.io.IOException;
import java.security.cert.CertificateException;
import java.security.cert.X509CRL;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import org.apache.commons.lang3.ArrayUtils;
import org.mozilla.jss.crypto.SignatureAlgorithm;
import org.mozilla.jss.netscape.security.pkcs.PKCS7;
import org.mozilla.jss.netscape.security.x509.X509CRLImpl;
import org.mozilla.jss.netscape.security.x509.X509CertImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Cert {
private static Logger logger = LoggerFactory.getLogger(Cert.class);
public static final String HEADER = "-----BEGIN CERTIFICATE-----";
public static final String FOOTER = "-----END CERTIFICATE-----";
public static final String PKCS7_HEADER = "-----BEGIN PKCS7-----";
public static final String PKCS7_FOOTER = "-----END PKCS7-----";
// From https://www.rfc-editor.org/rfc/rfc7468.txt
public static final String REQUEST_HEADER = "-----BEGIN CERTIFICATE REQUEST-----";
public static final String REQUEST_FOOTER = "-----END CERTIFICATE REQUEST-----";
public static SignatureAlgorithm mapAlgorithmToJss(String algname) {
if (algname.equals("MD5withRSA"))
return SignatureAlgorithm.RSASignatureWithMD5Digest;
else if (algname.equals("MD2withRSA"))
return SignatureAlgorithm.RSASignatureWithMD2Digest;
else if (algname.equals("SHA1withRSA"))
return SignatureAlgorithm.RSASignatureWithSHA1Digest;
else if (algname.equals("SHA1withDSA"))
return SignatureAlgorithm.DSASignatureWithSHA1Digest;
else if (algname.equals("SHA256withRSA"))
return SignatureAlgorithm.RSASignatureWithSHA256Digest;
else if (algname.equals("SHA384withRSA"))
return SignatureAlgorithm.RSASignatureWithSHA384Digest;
else if (algname.equals("SHA512withRSA"))
return SignatureAlgorithm.RSASignatureWithSHA512Digest;
else if (algname.equals("SHA1withEC"))
return SignatureAlgorithm.ECSignatureWithSHA1Digest;
else if (algname.equals("SHA256withEC"))
return SignatureAlgorithm.ECSignatureWithSHA256Digest;
else if (algname.equals("SHA384withEC"))
return SignatureAlgorithm.ECSignatureWithSHA384Digest;
else if (algname.equals("SHA512withEC"))
return SignatureAlgorithm.ECSignatureWithSHA512Digest;
else if (algname.equals("SHA256withRSA/PSS"))
return SignatureAlgorithm.RSAPSSSignatureWithSHA256Digest;
else if (algname.equals("SHA384withRSA/PSS"))
return SignatureAlgorithm.RSAPSSSignatureWithSHA384Digest;
else if (algname.equals("SHA512withRSA/PSS"))
return SignatureAlgorithm.RSAPSSSignatureWithSHA512Digest;
return null;
}
public static String stripBrackets(String s) {
if (s == null) {
return s;
}
if (s.startsWith(HEADER) && s.endsWith(FOOTER)) {
return s.substring(HEADER.length(), s.length() - FOOTER.length());
}
if (s.startsWith(PKCS7_HEADER) && s.endsWith(PKCS7_FOOTER)) {
return s.substring(PKCS7_HEADER.length(), s.length() - PKCS7_FOOTER.length());
}
// To support Thawte's header and footer
if ((s.startsWith("-----BEGIN PKCS #7 SIGNED DATA-----")) &&
(s.endsWith("-----END PKCS #7 SIGNED DATA-----"))) {
return (s.substring(35, (s.length() - 33)));
}
return s;
}
public static String stripCRLBrackets(String s) {
if (s == null) {
return s;
}
if ((s.startsWith("-----BEGIN CERTIFICATE REVOCATION LIST-----")) &&
(s.endsWith("-----END CERTIFICATE REVOCATION LIST-----"))) {
return (s.substring(43, (s.length() - 41)));
}
return s;
}
public static String stripCertBrackets(String s) {
return stripBrackets(s);
}
// private static BASE64Decoder mDecoder = new BASE64Decoder();
public static X509CertImpl mapCert(String mime64)
throws IOException {
mime64 = stripCertBrackets(mime64.trim());
String newval = normalizeCertStr(mime64);
// byte rawPub[] = mDecoder.decodeBuffer(newval);
byte[] rawPub = Utils.base64decode(newval);
X509CertImpl cert = null;
try {
cert = new X509CertImpl(rawPub);
} catch (CertificateException e) {
}
return cert;
}
public static X509Certificate[] mapCertFromPKCS7(String mime64)
throws IOException {
mime64 = stripCertBrackets(mime64.trim());
String newval = normalizeCertStr(mime64);
// byte rawPub[] = mDecoder.decodeBuffer(newval);
byte[] rawPub = Utils.base64decode(newval);
PKCS7 p7 = null;
try {
p7 = new PKCS7(rawPub);
} catch (Exception e) {
throw new IOException("Unable to parse PKCS #7 data: " + e.getMessage(), e);
}
return p7.getCertificates();
}
public static X509CRL mapCRL(String mime64)
throws IOException {
mime64 = stripCRLBrackets(mime64.trim());
String newval = normalizeCertStr(mime64);
// byte rawPub[] = mDecoder.decodeBuffer(newval);
byte[] rawPub = Utils.base64decode(newval);
X509CRL crl = null;
try {
crl = new X509CRLImpl(rawPub);
} catch (Exception e) {
}
return crl;
}
public static X509CRL mapCRL1(String mime64)
throws IOException {
mime64 = stripCRLBrackets(mime64.trim());
byte[] rawPub = Utils.base64decode(mime64);
X509CRL crl = null;
try {
crl = new X509CRLImpl(rawPub);
} catch (Exception e) {
throw new IOException(e.toString());
}
return crl;
}
public static String normalizeCertStr(String s) {
StringBuilder val = new StringBuilder();
if (s != null) {
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == '\n' ||
s.charAt(i) == '\r' ||
s.charAt(i) == '"' ||
s.charAt(i) == ' ') {
continue;
}
val.append(s.charAt(i));
}
}
return val.toString();
}
public static String normalizeCertStrAndReq(String s) {
StringBuilder val = new StringBuilder();
if (s != null) {
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == '\n' ||
s.charAt(i) == '\r' ||
s.charAt(i) == '"') {
continue;
}
val.append(s.charAt(i));
}
}
return val.toString();
}
public static byte[] parseCertificate(String cert) {
String encoded = normalizeCertStrAndReq(cert);
String b64 = stripBrackets(encoded);
return Utils.base64decode(b64);
}
/**
* Sorts certificate chain from root to leaf.
*
* This method sorts an array of certificates (e.g. from a PKCS #7
* data) that represents a certificate chain from root to leaf
* according to the subject DNs and issuer DNs.
*
* The input array is a set of certificates that are part of a
* chain but not in specific order.
*
* The result is a new array that contains the certificate chain
* sorted from root to leaf. The input array is unchanged.
*
* @param certs input array of certificates
* @return new array containing sorted certificates
*/
public static java.security.cert.X509Certificate[] sortCertificateChain(java.security.cert.X509Certificate[] certs) throws Exception {
if (certs == null) {
return null;
}
if (certs.length == 0) {
return certs;
}
// lookup map: subject DN -> cert
Map certMap = new LinkedHashMap<>();
// hierarchy map: subject DN -> issuer DN
Map parentMap = new HashMap<>();
// reverse hierarchy map: issuer DN -> subject DN
Map childMap = new HashMap<>();
// build maps
for (java.security.cert.X509Certificate cert : certs) {
String subjectDN = cert.getSubjectX500Principal().toString();
String issuerDN = cert.getIssuerX500Principal().toString();
if (certMap.containsKey(subjectDN)) {
throw new Exception("Duplicate certificate: " + subjectDN);
}
certMap.put(subjectDN, cert);
// ignore self-signed certificate
if (subjectDN.equals(issuerDN)) continue;
if (childMap.containsKey(issuerDN)) {
throw new Exception("Branched chain: " + issuerDN);
}
parentMap.put(subjectDN, issuerDN);
childMap.put(issuerDN, subjectDN);
}
if (logger.isDebugEnabled()) {
logger.debug("Certificates:");
for (String subjectDN : certMap.keySet()) {
logger.debug(" - " + subjectDN);
String parent = parentMap.get(subjectDN);
if (parent != null) logger.debug(" parent: " + parent);
String child = childMap.get(subjectDN);
if (child != null) logger.debug(" child: " + child);
}
}
// find leaf cert by removing certs that has a child
List leafCerts = new ArrayList<>();
leafCerts.addAll(certMap.keySet());
leafCerts.removeAll(childMap.keySet());
if (leafCerts.isEmpty()) {
throw new Exception("Unable to find leaf certificate");
}
if (leafCerts.size() > 1) {
StringBuilder sb = new StringBuilder();
for (String subjectDN : leafCerts) {
if (sb.length() > 0) sb.append(", ");
sb.append("[" + subjectDN + "]");
}
throw new Exception("Multiple leaf certificates: " + sb);
}
// build sorted chain
LinkedList chain = new LinkedList<>();
// start from leaf
String current = leafCerts.get(0);
while (current != null) {
java.security.cert.X509Certificate cert = certMap.get(current);
if (cert == null) {
// incomplete chain
break;
}
// add to the beginning of chain
chain.addFirst(cert);
// follow parent to root
current = parentMap.get(current);
}
return chain.toArray(new java.security.cert.X509Certificate[chain.size()]);
}
public static java.security.cert.X509Certificate[] sortCertificateChain(
java.security.cert.X509Certificate[] certs,
boolean reverse) throws Exception {
certs = sortCertificateChain(certs);
if (reverse) {
ArrayUtils.reverse(certs);
}
return certs;
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/util/CertPrettyPrint.java 0000664 0000000 0000000 00000031740 14565430767 0031364 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.util;
import java.security.MessageDigest;
import java.security.PublicKey;
import java.security.cert.Certificate;
import java.text.DateFormat;
import java.util.Locale;
import java.util.ResourceBundle;
import java.util.TimeZone;
import org.mozilla.jss.asn1.ASN1Util;
import org.mozilla.jss.asn1.SET;
import org.mozilla.jss.netscape.security.x509.CertificateExtensions;
import org.mozilla.jss.netscape.security.x509.CertificateX509Key;
import org.mozilla.jss.netscape.security.x509.Extension;
import org.mozilla.jss.netscape.security.x509.X509CertImpl;
import org.mozilla.jss.netscape.security.x509.X509CertInfo;
import org.mozilla.jss.netscape.security.x509.X509Key;
import org.mozilla.jss.pkcs7.ContentInfo;
import org.mozilla.jss.pkcs7.SignedData;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This class will display the certificate content in predefined
* format.
*
* @author Jack Pan-Chen
* @version $Revision$, $Date$
*/
public class CertPrettyPrint {
/*==========================================================
* constants
*==========================================================*/
private static final String CUSTOM_LOCALE = "Custom";
private static final Logger logger = LoggerFactory.getLogger(CertPrettyPrint.class);
/*==========================================================
* variables
*==========================================================*/
private X509CertImpl mX509Cert = null;
private PrettyPrintFormat pp = null;
private byte[] mCert_b = null;
/*==========================================================
* constructors
*==========================================================*/
public CertPrettyPrint(Certificate cert) {
if (cert instanceof X509CertImpl)
mX509Cert = (X509CertImpl) cert;
pp = new PrettyPrintFormat(":");
}
public CertPrettyPrint(byte[] certb) {
mCert_b = certb;
pp = new PrettyPrintFormat(":");
}
/*==========================================================
* public methods
*==========================================================*/
/**
* This method return string representation of the certificate
* in predefined format using specified client local. I18N Support.
*
* @param clientLocale Locale to be used for localization
* @return string representation of the certificate
*/
public String toString(Locale clientLocale) {
if (mX509Cert != null)
return X509toString(clientLocale);
else if (mCert_b != null)
return pkcs7toString(clientLocale);
else
return null;
}
public String pkcs7toString(Locale clientLocale) {
StringBuffer content=new StringBuffer();
try {
mX509Cert = new X509CertImpl(mCert_b);
return toString(clientLocale);
} catch (Exception e) {
}
ContentInfo ci = null;
try {
ci = (ContentInfo)
ASN1Util.decode(ContentInfo.getTemplate(), mCert_b);
} catch (Exception e) {
return "";
}
if (ci.getContentType().equals(ContentInfo.SIGNED_DATA)) {
SignedData sd = null;
try {
sd = (SignedData) ci.getInterpretedContent();
} catch (Exception e) {
return "";
}
if (sd.hasCertificates()) {
SET certs = sd.getCertificates();
for (int i = 0; i < certs.size(); i++) {
org.mozilla.jss.pkix.cert.Certificate cert =
(org.mozilla.jss.pkix.cert.Certificate) certs.elementAt(i);
X509CertImpl certImpl = null;
try {
certImpl = new X509CertImpl(
ASN1Util.encode(cert));
} catch (Exception e) {
}
CertPrettyPrint print = new CertPrettyPrint(certImpl);
content.append(print.toString(Locale.getDefault()));
content.append("\n");
}
return content.toString();
}
}
return content.toString();
}
public String stripCertBrackets(String s) {
if (s == null) {
return s;
}
if ((s.startsWith(Cert.HEADER)) &&
(s.endsWith(Cert.FOOTER))) {
return (s.substring(27, (s.length() - 25)));
}
// To support Thawte's header and footer
if ((s.startsWith("-----BEGIN PKCS #7 SIGNED DATA-----")) &&
(s.endsWith("-----END PKCS #7 SIGNED DATA-----"))) {
return (s.substring(35, (s.length() - 33)));
}
return s;
}
public String normalizeCertStr(String s) {
StringBuffer val = new StringBuffer();
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == '\n') {
continue;
} else if (s.charAt(i) == '\r') {
continue;
} else if (s.charAt(i) == '"') {
continue;
} else if (s.charAt(i) == ' ') {
continue;
}
val.append(s.charAt(i));
}
return val.toString();
}
public String X509toString(Locale clientLocale) {
//get I18N resources
ResourceBundle resource = ResourceBundle.getBundle(
PrettyPrintResources.class.getName());
DateFormat dateFormater = DateFormat.getDateTimeInstance(
DateFormat.FULL, DateFormat.FULL, clientLocale);
//get timezone and timezone ID
String tz = " ";
String tzid = " ";
StringBuffer sb = new StringBuffer();
try {
X509CertInfo info = (X509CertInfo) mX509Cert.get(
X509CertImpl.NAME + "." + X509CertImpl.INFO);
String serial2 = mX509Cert.getSerialNumber().toString(16).toUpperCase();
//get correct instance of key
PublicKey pKey = mX509Cert.getPublicKey();
X509Key key = null;
if (pKey instanceof CertificateX509Key) {
CertificateX509Key certKey = (CertificateX509Key) pKey;
key = (X509Key) certKey.get(CertificateX509Key.KEY);
}
if (pKey instanceof X509Key) {
key = (X509Key) pKey;
}
//take care of spki
sb.append(pp.indent(4) + resource.getString(
PrettyPrintResources.TOKEN_CERTIFICATE) + "\n");
sb.append(pp.indent(8) + resource.getString(
PrettyPrintResources.TOKEN_DATA) + "\n");
sb.append(pp.indent(12) + resource.getString(
PrettyPrintResources.TOKEN_VERSION) + " v");
sb.append((mX509Cert.getVersion() + 1) + "\n");
sb.append(pp.indent(12) + resource.getString(
PrettyPrintResources.TOKEN_SERIAL) + "0x" + serial2 + "\n");
//XXX I18N Algorithm Name ?
sb.append(pp.indent(12) + resource.getString(
PrettyPrintResources.TOKEN_SIGALG) + mX509Cert.getSigAlgName() +
" - " + mX509Cert.getSigAlgOID() + "\n");
//XXX I18N IssuerDN ?
sb.append(pp.indent(12) + resource.getString(
PrettyPrintResources.TOKEN_ISSUER) +
mX509Cert.getIssuerX500Principal() + "\n");
sb.append(pp.indent(12) + resource.getString(
PrettyPrintResources.TOKEN_VALIDITY) + "\n");
String notBefore = dateFormater.format(mX509Cert.getNotBefore());
String notAfter = dateFormater.format(mX509Cert.getNotAfter());
//get timezone and timezone ID
if (TimeZone.getDefault() != null) {
tz = TimeZone.getDefault().getDisplayName(
TimeZone.getDefault().inDaylightTime(
mX509Cert.getNotBefore()),
TimeZone.SHORT,
clientLocale);
tzid = TimeZone.getDefault().getID();
}
// Specify notBefore
if (tz.equals(tzid) || tzid.equals(CUSTOM_LOCALE)) {
// Do NOT append timezone ID
sb.append(pp.indent(16)
+ resource.getString(
PrettyPrintResources.TOKEN_NOT_BEFORE)
+ notBefore
+ "\n");
} else {
// Append timezone ID
sb.append(pp.indent(16)
+ resource.getString(
PrettyPrintResources.TOKEN_NOT_BEFORE)
+ notBefore
+ " " + tzid + "\n");
}
// re-get timezone (just in case it is different . . .)
if (TimeZone.getDefault() != null) {
tz = TimeZone.getDefault().getDisplayName(
TimeZone.getDefault().inDaylightTime(
mX509Cert.getNotAfter()),
TimeZone.SHORT,
clientLocale);
}
// Specify notAfter
if (tz.equals(tzid) || tzid.equals(CUSTOM_LOCALE)) {
// Do NOT append timezone ID
sb.append(pp.indent(16)
+ resource.getString(
PrettyPrintResources.TOKEN_NOT_AFTER)
+ notAfter
+ "\n");
} else {
// Append timezone ID
sb.append(pp.indent(16)
+ resource.getString(
PrettyPrintResources.TOKEN_NOT_AFTER)
+ notAfter
+ " " + tzid + "\n");
}
//XXX I18N SubjectDN ?
sb.append(pp.indent(12) + resource.getString(
PrettyPrintResources.TOKEN_SUBJECT) +
mX509Cert.getSubjectX500Principal() + "\n");
sb.append(pp.indent(12) + resource.getString(
PrettyPrintResources.TOKEN_SPKI) + "\n");
PubKeyPrettyPrint pkpp = new PubKeyPrettyPrint(key);
sb.append(pkpp.toString(clientLocale, 16, 16));
//take care of extensions
CertificateExtensions extensions = (CertificateExtensions)
info.get(X509CertInfo.EXTENSIONS);
sb.append(pp.indent(12) + resource.getString(
PrettyPrintResources.TOKEN_EXTENSIONS) + "\n");
if (extensions != null)
for (int i = 0; i < extensions.size(); i++) {
Extension ext = extensions.elementAt(i);
ExtPrettyPrint extpp = new ExtPrettyPrint(ext, 16);
sb.append(extpp.toString());
}
//take care of signature
sb.append(pp.indent(8) + resource.getString(
PrettyPrintResources.TOKEN_SIGNATURE) + "\n");
//XXX I18N Algorithm Name ?
sb.append(pp.indent(12) + resource.getString(
PrettyPrintResources.TOKEN_ALGORITHM) +
mX509Cert.getSigAlgName() + " - " + mX509Cert.getSigAlgOID() + "\n");
sb.append(pp.indent(12) + resource.getString(
PrettyPrintResources.TOKEN_SIGNATURE) + "\n");
sb.append(pp.toHexString(mX509Cert.getSignature(), 16, 16));
// fingerprints
String[] hashes = new String[] { "MD2", "MD5", "SHA-1", "SHA-256", "SHA-512" };
StringBuffer certFingerprints = new StringBuffer();
sb.append(pp.indent(8) + "FingerPrint\n");
for (int i = 0; i < hashes.length; i++) {
MessageDigest md = MessageDigest.getInstance(hashes[i]);
md.update(mX509Cert.getEncoded());
certFingerprints.append(pp.indent(12) + hashes[i] + ":\n" +
pp.toHexString(md.digest(), 16, 16));
}
sb.append(certFingerprints.toString());
} catch (Exception e) {
logger.error("Problem converting to string", e);
}
return sb.toString();
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/util/CrlPrettyPrint.java 0000664 0000000 0000000 00000030144 14565430767 0031204 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.util;
import java.text.DateFormat;
import java.util.Iterator;
import java.util.Locale;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.TimeZone;
import org.mozilla.jss.netscape.security.x509.CRLExtensions;
import org.mozilla.jss.netscape.security.x509.Extension;
import org.mozilla.jss.netscape.security.x509.RevokedCertificate;
import org.mozilla.jss.netscape.security.x509.X509CRLImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This class will display the certificate content in predefined
* format.
*
* @author Andrew Wnuk
* @version $Revision$, $Date$
*/
public class CrlPrettyPrint {
/*==========================================================
* constants
*==========================================================*/
private static final String CUSTOM_LOCALE = "Custom";
private static final Logger logger = LoggerFactory.getLogger(CrlPrettyPrint.class);
/*==========================================================
* variables
*==========================================================*/
private X509CRLImpl mCRL = null;
private PrettyPrintFormat pp = null;
/*==========================================================
* constructors
*==========================================================*/
public CrlPrettyPrint(X509CRLImpl crl) {
mCRL = crl;
pp = new PrettyPrintFormat(":");
}
/*==========================================================
* public methods
*==========================================================*/
/**
* This method return string representation of the certificate
* revocation list in predefined format using specified client
* local. I18N Support.
*
* @param clientLocale Locale to be used for localization
* @return string representation of the certificate
*/
public String toString(Locale clientLocale) {
return toString(clientLocale, 0, 0, 0);
}
public String toString(Locale clientLocale, long crlSize, long pageStart, long pageSize) {
//get I18N resources
ResourceBundle resource = ResourceBundle.getBundle(
PrettyPrintResources.class.getName());
DateFormat dateFormater = DateFormat.getDateTimeInstance(
DateFormat.FULL, DateFormat.FULL, clientLocale);
//get timezone and timezone ID
String tz = " ";
String tzid = " ";
StringBuffer sb = new StringBuffer();
try {
sb.append(pp.indent(4) + resource.getString(
PrettyPrintResources.TOKEN_CRL) + "\n");
sb.append(pp.indent(8) + resource.getString(
PrettyPrintResources.TOKEN_DATA) + "\n");
sb.append(pp.indent(12) + resource.getString(
PrettyPrintResources.TOKEN_VERSION) + " v");
sb.append((mCRL.getVersion() + 1) + "\n");
sb.append(pp.indent(12) + resource.getString(
PrettyPrintResources.TOKEN_SIGALG) + mCRL.getSigAlgName() +
" - " + mCRL.getSigAlgOID() + "\n");
sb.append(pp.indent(12) + resource.getString(
PrettyPrintResources.TOKEN_ISSUER) +
mCRL.getIssuerDN().toString() + "\n");
// Format thisUpdate
String thisUpdate = dateFormater.format(mCRL.getThisUpdate());
// get timezone and timezone ID
if (TimeZone.getDefault() != null) {
tz = TimeZone.getDefault().getDisplayName(
TimeZone.getDefault().inDaylightTime(
mCRL.getThisUpdate()),
TimeZone.SHORT,
clientLocale);
tzid = TimeZone.getDefault().getID();
}
// Specify ThisUpdate
if (tz.equals(tzid) || tzid.equals(CUSTOM_LOCALE)) {
// Do NOT append timezone ID
sb.append(pp.indent(12)
+ resource.getString(
PrettyPrintResources.TOKEN_THIS_UPDATE)
+ thisUpdate
+ "\n");
} else {
// Append timezone ID
sb.append(pp.indent(12)
+ resource.getString(
PrettyPrintResources.TOKEN_THIS_UPDATE)
+ thisUpdate
+ " " + tzid + "\n");
}
// Check for presence of NextUpdate
if (mCRL.getNextUpdate() != null) {
// Format nextUpdate
String nextUpdate = dateFormater.format(mCRL.getNextUpdate());
// re-get timezone (just in case it is different . . .)
if (TimeZone.getDefault() != null) {
tz = TimeZone.getDefault().getDisplayName(
TimeZone.getDefault().inDaylightTime(
mCRL.getNextUpdate()),
TimeZone.SHORT,
clientLocale);
}
// Specify NextUpdate
if (tz.equals(tzid) || tzid.equals(CUSTOM_LOCALE)) {
// Do NOT append timezone ID
sb.append(pp.indent(12)
+ resource.getString(
PrettyPrintResources.TOKEN_NEXT_UPDATE)
+ nextUpdate
+ "\n");
} else {
// Append timezone ID
sb.append(pp.indent(12)
+ resource.getString(
PrettyPrintResources.TOKEN_NEXT_UPDATE)
+ nextUpdate
+ " " + tzid + "\n");
}
}
if (crlSize > 0 && pageStart == 0 && pageSize == 0) {
sb.append(pp.indent(12) + resource.getString(
PrettyPrintResources.TOKEN_REVOKED_CERTIFICATES) + crlSize + "\n");
} else if ((crlSize == 0 && pageStart == 0 && pageSize == 0) ||
(crlSize > 0 && pageStart > 0 && pageSize > 0)) {
sb.append(pp.indent(12) + resource.getString(
PrettyPrintResources.TOKEN_REVOKED_CERTIFICATES));
if (crlSize > 0 && pageStart > 0 && pageSize > 0) {
long upperLimit = (pageStart + pageSize - 1 > crlSize) ? crlSize : pageStart + pageSize - 1;
sb.append("" + pageStart + "-" + upperLimit + " of " + crlSize);
}
sb.append("\n");
Set revokedCerts = mCRL.getRevokedCertificates();
if (revokedCerts != null) {
Iterator i = revokedCerts.iterator();
long l = 1;
while ((i.hasNext()) && ((crlSize == 0) || (pageStart + pageSize > l))) {
RevokedCertificate revokedCert = i.next();
if ((crlSize == 0) || ((pageStart <= l) && (pageStart + pageSize > l))) {
sb.append(pp.indent(16) + resource.getString(
PrettyPrintResources.TOKEN_SERIAL) + "0x" +
revokedCert.getSerialNumber().toString(16).toUpperCase() + "\n");
String revocationDate =
dateFormater.format(revokedCert.getRevocationDate());
// re-get timezone
// (just in case it is different . . .)
if (TimeZone.getDefault() != null) {
tz = TimeZone.getDefault().getDisplayName(
TimeZone.getDefault().inDaylightTime(
revokedCert.getRevocationDate()),
TimeZone.SHORT,
clientLocale);
}
// Specify revocationDate
if (tz.equals(tzid) ||
tzid.equals(CUSTOM_LOCALE)) {
// Do NOT append timezone ID
sb.append(pp.indent(16)
+ resource.getString(
PrettyPrintResources.TOKEN_REVOCATION_DATE)
+ revocationDate
+ "\n");
} else {
// Append timezone ID
sb.append(pp.indent(16)
+ resource.getString(
PrettyPrintResources.TOKEN_REVOCATION_DATE)
+ revocationDate
+ " " + tzid + "\n");
}
if (revokedCert.hasExtensions()) {
sb.append(pp.indent(16) + resource.getString(
PrettyPrintResources.TOKEN_EXTENSIONS) + "\n");
CRLExtensions crlExtensions = revokedCert.getExtensions();
if (crlExtensions != null) {
for (int k = 0; k < crlExtensions.size(); k++) {
Extension ext = crlExtensions.elementAt(k);
ExtPrettyPrint extpp = new ExtPrettyPrint(ext, 20);
sb.append(extpp.toString());
}
}
}
}
l++;
}
}
}
CRLExtensions crlExtensions = mCRL.getExtensions();
if (crlExtensions != null) {
sb.append(pp.indent(8) + resource.getString(
PrettyPrintResources.TOKEN_EXTENSIONS) + "\n");
for (int k = 0; k < crlExtensions.size(); k++) {
Extension ext = crlExtensions.elementAt(k);
ExtPrettyPrint extpp = new ExtPrettyPrint(ext, 12);
sb.append(extpp.toString());
}
}
//take care of signature
sb.append(pp.indent(8) + resource.getString(
PrettyPrintResources.TOKEN_SIGNATURE) + "\n");
//XXX I18N Algorithm Name ?
sb.append(pp.indent(12) + resource.getString(
PrettyPrintResources.TOKEN_ALGORITHM) +
mCRL.getSigAlgName() + " - " + mCRL.getSigAlgOID() + "\n");
sb.append(pp.indent(12) + resource.getString(
PrettyPrintResources.TOKEN_SIGNATURE) + "\n");
sb.append(pp.toHexString(mCRL.getSignature(), 16, 16));
} catch (Exception e) {
sb.append("\n\n" + pp.indent(4) + resource.getString(
PrettyPrintResources.TOKEN_DECODING_ERROR) + "\n\n");
logger.debug("Problem converting to string", e);
}
return sb.toString();
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/util/DerEncoder.java 0000664 0000000 0000000 00000002521 14565430767 0030247 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.util;
import java.io.IOException;
import java.io.OutputStream;
/**
* Interface to an object that knows how to write its own DER
* encoding to an output stream.
*
* @version 1.2 97/12/10
* @author D. N. Hoover
*/
public interface DerEncoder {
/**
* DER encode this object and write the results to a stream.
*
* @param out the stream on which the DER encoding is written.
* @throws IOException If an error occurred.
*/
public void derEncode(OutputStream out)
throws IOException;
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/util/DerInputBuffer.java 0000664 0000000 0000000 00000013010 14565430767 0031114 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.util;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.OutputStream;
/**
* DER input buffer ... this is the main abstraction in the DER library
* which actively works with the "untyped byte stream" abstraction. It
* does so with impunity, since it's not intended to be exposed to the
* anyone who could violate the "typed value stream" DER model and hence
* corrupt the input stream of DER values.
*
* @version 1.11
* @author David Brownell
*/
class DerInputBuffer extends ByteArrayInputStream implements Cloneable {
DerInputBuffer(byte[] buf) {
super(buf);
}
DerInputBuffer(byte[] buf, int offset, int len) {
super(buf, offset, len);
}
DerInputBuffer dup() {
try {
DerInputBuffer retval = (DerInputBuffer) clone();
retval.mark(Integer.MAX_VALUE);
return retval;
} catch (CloneNotSupportedException e) {
throw new IllegalArgumentException(e.toString());
}
}
byte[] toByteArray() throws IOException {
int len = available();
if (len <= 0)
throw new IOException("No Buffer Space Available.");
byte[] retval = new byte[len];
System.arraycopy(buf, pos, retval, 0, len);
return retval;
}
int peek() throws IOException {
if (pos >= count)
throw new IOException("out of data");
else
return buf[pos];
}
/**
* Compares this DerInputBuffer for equality with the specified
* object.
*/
@Override
public boolean equals(Object other) {
if (other instanceof DerInputBuffer)
return equals((DerInputBuffer) other);
else
return false;
}
boolean equals(DerInputBuffer other) {
if (this == other)
return true;
int max = this.available();
if (other.available() != max)
return false;
for (int i = 0; i < max; i++) {
if (this.buf[this.pos + i] != other.buf[other.pos + i]) {
return false;
}
}
return true;
}
void truncate(int len) throws IOException {
if (len > available())
throw new IOException("insufficient data");
count = pos + len;
}
/**
* Returns the unsigned integer which takes up the specified number
* of bytes in this buffer.
*/
BigInt getUnsigned(int len) throws IOException {
if (len > available())
throw new IOException("short read, getInteger");
/*
* A prepended zero is used to ensure that the integer is
* interpreted as unsigned even when the high order bit is
* zero. We don't support signed BigInts.
*
* Fix this here ... BigInts aren't expected to have these,
* and stuff like signing (sigsize = f(modulus)) misbehaves.
*/
if (len > 1 && buf[pos] == 0) {
len--;
skip(1);
}
/*
* Consume the rest of the buffer, returning its value as
* an unsigned integer.
*/
byte[] bytes = new byte[len];
System.arraycopy(buf, pos, bytes, 0, len);
skip(len);
return new BigInt(bytes);
}
/**
* Returns the bit string which takes up the rest of this buffer.
* This bit string must be byte-aligned.
*/
byte[] getBitString() {
if (pos >= count || buf[pos] != 0)
return null;
/*
* Just copy the data into an aligned, padded octet buffer,
* and consume the rest of the buffer.
*/
int len = available();
byte[] retval = new byte[len - 1];
System.arraycopy(buf, pos + 1, retval, 0, len - 1);
pos = count;
return retval;
}
/**
* Returns the bit string which takes up the rest of this buffer.
* The bit string need not be byte-aligned.
*/
BitArray getUnalignedBitString() {
if (pos >= count)
return null;
/*
* Just copy the data into an aligned, padded octet buffer,
* and consume the rest of the buffer.
*/
int len = available();
byte[] bits = new byte[len - 1];
int length = bits.length * 8 - buf[pos]; // number of valid bits
System.arraycopy(buf, pos + 1, bits, 0, len - 1);
BitArray bitArray = new BitArray(length, bits);
pos = count;
return bitArray;
}
/**
* Package-access method to optimize output operations
*/
void dump(OutputStream out, int length) throws IOException {
if (count < mark + length)
throw new IOException("short DER value (encode)");
out.write(buf, mark, length);
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/util/DerInputStream.java 0000664 0000000 0000000 00000054430 14565430767 0031151 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.util;
import java.io.IOException;
import java.io.InputStream;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;
import java.util.Vector;
/**
* A DER input stream, used for parsing ASN.1 DER-encoded data such as
* that found in X.509 certificates. DER is a subset of BER/1, which has
* the advantage that it allows only a single encoding of primitive data.
* (High level data such as dates still support many encodings.) That is,
* it uses the "Definite" Encoding Rules (DER) not the "Basic" ones (BER).
*
*
* Note that, like BER/1, DER streams are streams of explicitly tagged data values. Accordingly, this programming
* interface does not expose any variant of the java.io.InputStream interface, since that kind of input stream holds
* untagged data values and using that I/O model could prevent correct parsing of the DER data.
*
*
* At this time, this class supports only a subset of the types of DER data encodings which are defined. That subset is
* sufficient for parsing most X.509 certificates.
*
* @version 1.35
*
* @author David Brownell
* @author Amit Kapoor
* @author Hemma Prafullchandra
*/
public class DerInputStream {
/*
* This version only supports fully buffered DER. This is easy to
* work with, though if large objects are manipulated DER becomes
* awkward to deal with. That's where BER is useful, since BER
* handles streaming data relatively well.
*/
DerInputBuffer buffer;
/**
* Create a DER input stream from a data buffer. The buffer is not
* copied, it is shared. Accordingly, the buffer should be treated
* as read-only.
*
* @param data the buffer from which to create the string (CONSUMED)
*/
public DerInputStream(byte[] data) {
buffer = new DerInputBuffer(data);
buffer.mark(Integer.MAX_VALUE);
}
/**
* Create a DER input stream from part of a data buffer.
* The buffer is not copied, it is shared. Accordingly, the
* buffer should be treated as read-only.
*
* @param data the buffer from which to create the string (CONSUMED)
* @param offset the first index of data which will
* be read as DER input in the new stream
* @param len how long a chunk of the buffer to use,
* starting at "offset"
*/
public DerInputStream(byte[] data, int offset, int len) {
buffer = new DerInputBuffer(data, offset, len);
buffer.mark(Integer.MAX_VALUE);
}
DerInputStream(DerInputBuffer buf) {
buffer = buf;
buffer.mark(Integer.MAX_VALUE);
}
/**
* Creates a new DER input stream from part of this input stream.
*
* @param len how long a chunk of the current input stream to use,
* starting at the current position.
* @param do_skip true if the existing data in the input stream should
* be skipped. If this value is false, the next data read
* on this stream and the newly created stream will be the
* same.
*/
public DerInputStream subStream(int len, boolean do_skip)
throws IOException {
DerInputBuffer newbuf = buffer.dup();
newbuf.truncate(len);
if (do_skip)
buffer.skip(len);
return new DerInputStream(newbuf);
}
/**
* Return what has been written to this DerInputStream
* as a byte array. Useful for debugging.
* @throws IOException
*/
public byte[] toByteArray() throws IOException {
return buffer.toByteArray();
}
/*
* PRIMITIVES -- these are "universal" ASN.1 simple types.
*
* INTEGER, BIT STRING, OCTET STRING, NULL
* OBJECT IDENTIFIER, SEQUENCE (OF), SET (OF)
* PrintableString, T61String, IA5String, UTCTime
*/
/**
* Get an (unsigned) integer from the input stream.
*/
public BigInt getInteger() throws IOException {
if (buffer.read() != DerValue.tag_Integer)
throw new IOException("DER input, Integer tag error");
return buffer.getUnsigned(getLength(buffer));
}
/**
* Get a bit string from the input stream. Only octet-aligned
* bitstrings (multiples of eight bits in length) are handled
* by this method.
*/
public byte[] getBitString() throws IOException {
if (buffer.read() != DerValue.tag_BitString)
throw new IOException("DER input not an bit string");
int length = getLength(buffer);
/*
* This byte affects alignment and padding (for the last byte).
* Use getUnalignedBitString() for none 8-bit aligned bit strings.
*/
if (buffer.read() != 0)
return null;
length--;
/*
* Just read the data into an aligned, padded octet buffer.
*/
byte[] retval = new byte[length];
if (buffer.read(retval) != length)
throw new IOException("short read of DER bit string");
return retval;
}
/**
* Get a bit string from the input stream. The bit string need
* not be byte-aligned.
*/
public BitArray getUnalignedBitString() throws IOException {
if (buffer.read() != DerValue.tag_BitString)
throw new IOException("DER input not a bit string");
int length = getLength(buffer) - 1;
/*
* First byte = number of excess bits in the last octet of the
* representation.
*/
int validBits = length * 8 - buffer.read();
byte[] repn = new byte[length];
if (buffer.read(repn) != length)
throw new IOException("short read of DER bit string");
return new BitArray(validBits, repn);
}
/**
* Returns an ASN.1 OCTET STRING from the input stream.
*/
public byte[] getOctetString() throws IOException {
if (buffer.read() != DerValue.tag_OctetString)
throw new IOException("DER input not an octet string");
int length = getLength(buffer);
byte[] retval = new byte[length];
if (buffer.read(retval) != length)
throw new IOException("short read of DER octet string");
return retval;
}
/**
* Returns the asked number of bytes from the input stream.
*/
public void getBytes(byte[] val) throws IOException {
if (val.length != 0) {
if (buffer.read(val) != val.length) {
throw new IOException("short read of DER octet string");
}
}
}
/**
* Reads an encoded null value from the input stream.
*/
public void getNull() throws IOException {
if (buffer.read() != DerValue.tag_Null || buffer.read() != 0)
throw new IOException("getNull, bad data");
}
/**
* Reads an X.200 style Object Identifier from the stream.
*/
public ObjectIdentifier getOID() throws IOException {
return new ObjectIdentifier(this);
}
/**
* Return a sequence of encoded entities. ASN.1 sequences are
* ordered, and they are often used, like a "struct" in C or C++,
* to group data values. They may have optional or context
* specific values.
*
* @param startLen guess about how long the sequence will be
* (used to initialize an auto-growing data structure)
* @return array of the values in the sequence
*/
public DerValue[] getSequence(int startLen) throws IOException {
int b = buffer.read();
if (b != DerValue.tag_Sequence)
throw new IOException("Sequence tag error " + b);
return readVector(startLen);
}
public void skipSequence(int startLen) throws IOException {
int b = buffer.read();
if (b != DerValue.tag_Sequence)
throw new IOException("Sequence tag error " + b);
int len = getLength(buffer);
buffer.skip(len);
}
/**
* Return a set of encoded entities. ASN.1 sets are unordered,
* though DER may specify an order for some kinds of sets (such
* as the attributes in an X.500 relative distinguished name)
* to facilitate binary comparisons of encoded values.
*
* @param startLen guess about how large the set will be
* (used to initialize an auto-growing data structure)
* @return array of the values in the sequence
*/
public DerValue[] getSet(int startLen) throws IOException {
if (buffer.read() != DerValue.tag_Set)
throw new IOException("Set tag error");
return readVector(startLen);
}
/**
* Return a set of encoded entities. ASN.1 sets are unordered,
* though DER may specify an order for some kinds of sets (such
* as the attributes in an X.500 relative distinguished name)
* to facilitate binary comparisons of encoded values.
*
* @param startLen guess about how large the set will be
* (used to initialize an auto-growing data structure)
* @param implicit if true tag is assumed implicit.
* @return array of the values in the sequence
*/
public DerValue[] getSet(int startLen, boolean implicit) throws IOException {
int tag = buffer.read();
if (!implicit) {
if (tag != DerValue.tag_Set) {
throw new IOException("Set tag error");
}
}
return (readVector(startLen));
}
/*
* Read a "vector" of values ... set or sequence have the
* same encoding, except for the initial tag, so both use
* this same helper routine.
*/
protected DerValue[] readVector(int startLen) throws IOException {
int len = getLength(buffer);
DerInputStream newstr;
if (len == 0)
// return empty array instead of null, which should be
// used only for missing optionals
return new DerValue[0];
/*
* Create a temporary stream from which to read the data,
* unless it's not really needed.
*/
if (buffer.available() == len)
newstr = this;
else
newstr = subStream(len, true);
/*
* Pull values out of the stream.
*/
Vector vec = new Vector<>(startLen);
DerValue value;
do {
value = new DerValue(newstr.buffer);
vec.addElement(value);
} while (newstr.available() > 0);
if (newstr.available() != 0)
throw new IOException("extra data at end of vector");
/*
* Now stick them into the array we're returning.
*/
int i, max = vec.size();
DerValue[] retval = new DerValue[max];
for (i = 0; i < max; i++)
retval[i] = vec.elementAt(i);
return retval;
}
/**
* Get a single DER-encoded value from the input stream.
* It can often be useful to pull a value from the stream
* and defer parsing it. For example, you can pull a nested
* sequence out with one call, and only examine its elements
* later when you really need to.
*/
public DerValue getDerValue() throws IOException {
return new DerValue(buffer);
}
public String getPrintableString() throws IOException {
return (new DerValue(buffer)).getPrintableString();
}
public String getT61String() throws IOException {
return (new DerValue(buffer)).getT61String();
}
public String getIA5String() throws IOException {
return (new DerValue(buffer)).getIA5String();
}
public String getBMPString() throws IOException {
return (new DerValue(buffer)).getBMPString();
}
public String getUniversalString() throws IOException {
return (new DerValue(buffer)).getUniversalString();
}
public String getDirectoryString() throws IOException {
return (new DerValue(buffer)).getDirectoryString();
}
/**
* Get a UTC encoded time value from the input stream.
*/
public Date getUTCTime() throws IOException {
if (buffer.read() != DerValue.tag_UtcTime)
throw new IOException("DER input, UTCtime tag invalid ");
if (buffer.available() < 11)
throw new IOException("DER input, UTCtime short input");
int len = getLength(buffer);
if (len < 11 || len > 17)
throw new IOException("DER getUTCTime length error");
/*
* UTC time encoded as ASCII chars, YYMMDDhhmmss.
* If YY <= 50, we assume 20YY;
* if YY > 50, we assume 19YY, as per IETF-PKIX part I.
*/
int year, month, day, hour, minute, second;
year = 10 * Character.digit((char) buffer.read(), 10);
year += Character.digit((char) buffer.read(), 10);
if (year <= 50) // origin 2000
year += 2000;
else
year += 1900; // origin 1900
month = 10 * Character.digit((char) buffer.read(), 10);
month += Character.digit((char) buffer.read(), 10);
month -= 1; // months are 0-11
day = 10 * Character.digit((char) buffer.read(), 10);
day += Character.digit((char) buffer.read(), 10);
hour = 10 * Character.digit((char) buffer.read(), 10);
hour += Character.digit((char) buffer.read(), 10);
minute = 10 * Character.digit((char) buffer.read(), 10);
minute += Character.digit((char) buffer.read(), 10);
len -= 10;
/**
* We allow for non-encoded seconds, even though the
* IETF-PKIX specification says that the seconds should
* always be encoded even if it is zero.
*/
if (len == 3 || len == 7) {
second = 10 * Character.digit((char) buffer.read(), 10);
second += Character.digit((char) buffer.read(), 10);
len -= 2;
} else
second = 0;
if (month < 0 || day <= 0
|| month > 11 || day > 31 || hour >= 24
|| minute >= 60 || second >= 60)
throw new IOException("Parse UTC time, invalid format");
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
cal.set(year, month, day, hour, minute, second);
cal.set(Calendar.MILLISECOND, 0); /* To clear millisecond field */
cal.set(Calendar.ERA, GregorianCalendar.AD);
Date readDate = cal.getTime();
long utcTime = readDate.getTime();
/*
* Finally, "Z" or "+hhmm" or "-hhmm" ... offsets change hhmm
*/
if (!(len == 1 || len == 5))
throw new IOException("Parse UTC time, invalid offset");
switch (buffer.read()) {
case '+': {
int Htmp = 10 * Character.digit((char) buffer.read(), 10);
Htmp += Character.digit((char) buffer.read(), 10);
int Mtmp = 10 * Character.digit((char) buffer.read(), 10);
Mtmp += Character.digit((char) buffer.read(), 10);
if (Htmp >= 24 || Mtmp >= 60)
throw new IOException("Parse UTCtime, +hhmm");
utcTime += ((Htmp * 60) + Mtmp) * 60 * 1000L;
}
break;
case '-': {
int Htmp = 10 * Character.digit((char) buffer.read(), 10);
Htmp += Character.digit((char) buffer.read(), 10);
int Mtmp = 10 * Character.digit((char) buffer.read(), 10);
Mtmp += Character.digit((char) buffer.read(), 10);
if (Htmp >= 24 || Mtmp >= 60)
throw new IOException("Parse UTCtime, -hhmm");
utcTime -= ((Htmp * 60) + Mtmp) * 60 * 1000L;
}
break;
case 'Z':
break;
default:
throw new IOException("Parse UTCtime, garbage offset");
}
readDate.setTime(utcTime);
return readDate;
}
/**
* Get a Generalized encoded time value from the input stream.
*/
public Date getGeneralizedTime() throws IOException {
if (buffer.read() != DerValue.tag_GeneralizedTime)
throw new IOException("DER input, GeneralizedTime tag invalid ");
if (buffer.available() < 13)
throw new IOException("DER input, GeneralizedTime short input");
int len = getLength(buffer);
/*
* Generalized time encoded as ASCII chars, YYYYMMDDhhmm[ss]
*/
int year, month, day, hour, minute, second;
year = 1000 * Character.digit((char) buffer.read(), 10);
year += 100 * Character.digit((char) buffer.read(), 10);
year += 10 * Character.digit((char) buffer.read(), 10);
year += Character.digit((char) buffer.read(), 10);
month = 10 * Character.digit((char) buffer.read(), 10);
month += Character.digit((char) buffer.read(), 10);
month -= 1; // Calendar months are 0-11
day = 10 * Character.digit((char) buffer.read(), 10);
day += Character.digit((char) buffer.read(), 10);
hour = 10 * Character.digit((char) buffer.read(), 10);
hour += Character.digit((char) buffer.read(), 10);
minute = 10 * Character.digit((char) buffer.read(), 10);
minute += Character.digit((char) buffer.read(), 10);
len -= 12;
/**
* We allow for non-encoded seconds, even though the
* IETF-PKIX specification says that the seconds should
* always be encoded even if it is zero.
*/
if (len == 3 || len == 7) {
second = 10 * Character.digit((char) buffer.read(), 10);
second += Character.digit((char) buffer.read(), 10);
len -= 2;
} else
second = 0;
if (month < 0 || day <= 0
|| month > 11 || day > 31 || hour >= 24
|| minute >= 60 || second >= 60)
throw new IOException("Parse Generalized time, invalid format");
/* Shouldn't this construct a Gregorian calendar directly???
* We don't really want locale dependant processing here */
Calendar cal = Calendar.getInstance(TimeZone.getTimeZone("GMT"));
cal.set(year, month, day, hour, minute, second);
cal.set(Calendar.MILLISECOND, 0); /* To clear millisecond field */
cal.set(Calendar.ERA, GregorianCalendar.AD);
Date readDate = cal.getTime();
long utcTime = readDate.getTime();
/*
* Finally, "Z" or "+hhmm" or "-hhmm" ... offsets change hhmm
*/
if (!(len == 1 || len == 5))
throw new IOException("Parse Generalized time, invalid offset");
switch (buffer.read()) {
case '+': {
int Htmp = 10 * Character.digit((char) buffer.read(), 10);
Htmp += Character.digit((char) buffer.read(), 10);
int Mtmp = 10 * Character.digit((char) buffer.read(), 10);
Mtmp += Character.digit((char) buffer.read(), 10);
if (Htmp >= 24 || Mtmp >= 60)
throw new IOException("Parse GeneralizedTime, +hhmm");
utcTime += ((Htmp * 60) + Mtmp) * 60 * 1000L;
}
break;
case '-': {
int Htmp = 10 * Character.digit((char) buffer.read(), 10);
Htmp += Character.digit((char) buffer.read(), 10);
int Mtmp = 10 * Character.digit((char) buffer.read(), 10);
Mtmp += Character.digit((char) buffer.read(), 10);
if (Htmp >= 24 || Mtmp >= 60)
throw new IOException("Parse GeneralizedTime, -hhmm");
utcTime -= ((Htmp * 60) + Mtmp) * 60 * 1000L;
}
break;
case 'Z':
break;
default:
throw new IOException("Parse GeneralizedTime, garbage offset");
}
readDate.setTime(utcTime);
return readDate;
}
/*
* Get a byte from the input stream.
*/
// package private
int getByte() throws IOException {
return (0x00ff & buffer.read());
}
public int peekByte() throws IOException {
return buffer.peek();
}
// package private
int getLength() throws IOException {
return getLength(buffer);
}
/*
* Get a length from the input stream, allowing for at most 32 bits of
* encoding to be used. (Not the same as getting a tagged integer!)
*/
static int getLength(InputStream in) throws IOException {
int value, tmp;
tmp = in.read();
if ((tmp & 0x080) == 0x00) { // 1 byte datum?
value = tmp;
} else { // no, more ...
tmp &= 0x07f;
/*
* NOTE: tmp == 0 indicates BER encoded data.
* tmp > 4 indicates more than 4Gb of data.
*/
if (tmp <= 0 || tmp > 4)
throw new IOException("DerInput.getLength(): lengthTag="
+ tmp + ", "
+ ((tmp == 0) ? "Indefinite length encoding not supported"
+ " or incorrect DER encoding."
: "too big."));
for (value = 0; tmp > 0; tmp--) {
value <<= 8;
value += 0x0ff & in.read();
}
}
return value;
}
/**
* Mark the current position in the buffer, so that
* a later call to reset
will return here.
*/
public void mark(int value) {
buffer.mark(value);
}
/**
* Return to the position of the last mark
call. A mark is implicitly set at the beginning of
* the stream when it is created.
*/
public void reset() {
buffer.reset();
}
/**
* Returns the number of bytes available for reading.
* This is most useful for testing whether the stream is
* empty.
*/
public int available() {
return buffer.available();
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/util/DerOutputStream.java 0000664 0000000 0000000 00000054353 14565430767 0031356 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.util;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.CharsetEncoder;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Comparator;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.TimeZone;
/**
* Output stream marshaling DER-encoded data. This is eventually provided
* in the form of a byte array; there is no advance limit on the size of
* that byte array.
*
*
* At this time, this class supports only a subset of the types of DER data encodings which are defined. That subset is
* sufficient for generating most X.509 certificates.
*
* @version 1.32
*
* @author David Brownell
* @author Amit Kapoor
* @author Hemma Prafullchandra
*/
public class DerOutputStream
extends ByteArrayOutputStream implements DerEncoder {
/**
* Construct an DER output stream.
*
* @param size how large a buffer to preallocate.
*/
public DerOutputStream(int size) {
super(size);
}
/**
* Construct an DER output stream.
*/
public DerOutputStream() {
}
/**
* Writes tagged, pre-marshaled data. This calcuates and encodes
* the length, so that the output data is the standard triple of
* { tag, length, data } used by all DER values.
*
* @param tag the DER value tag for the data, such as DerValue.tag_Sequence
* @param buf buffered data, which must be DER-encoded
*/
public void write(byte tag, byte[] buf) throws IOException {
write(tag);
putLength(buf.length);
write(buf, 0, buf.length);
}
/**
* Writes tagged data using buffer-to-buffer copy. As above,
* this writes a standard DER record. This is often used when
* efficiently encapsulating values in sequences.
*
* @param tag the DER value tag for the data, such as DerValue.tag_Sequence
* @param out buffered data
*/
public void write(byte tag, DerOutputStream out) throws IOException {
write(tag);
putLength(out.count);
write(out.buf, 0, out.count);
}
/**
* Writes implicitly tagged data using buffer-to-buffer copy. As above,
* this writes a standard DER record. This is often used when
* efficiently encapsulating implicitly tagged values.
*
* @param tag the DER value of the context-specific tag that replaces
* original tag of the value in the output , such as in
*
* {@literal } [N] IMPLICIT {@literal }
*
*
* For example, FooLength [1] IMPLICIT INTEGER, with value=4;
* would be encoded as "81 01 04" whereas in explicit
* tagging it would be encoded as "A1 03 02 01 04".
* Notice that the tag is A1 and not 81, this is because with
* explicit tagging the form is always constructed.
* @param value original value being implicitly tagged
*/
public void writeImplicit(byte tag, DerOutputStream value)
throws IOException {
write(tag);
write(value.buf, 1, value.count - 1);
}
/**
* Marshals pre-encoded DER value onto the output stream.
*/
public void putDerValue(DerValue val) throws IOException {
val.encode(this);
}
/*
* PRIMITIVES -- these are "universal" ASN.1 simple types.
*
* BOOLEAN, INTEGER, BIT STRING, OCTET STRING, NULL
* OBJECT IDENTIFIER, SEQUENCE(OF), SET(OF)
* PrintableString, T61String, IA5String, UTCTime
*/
/**
* Marshals a DER boolean on the output stream.
*/
public void putBoolean(boolean val) throws IOException {
write(DerValue.tag_Boolean);
putLength(1);
if (val) {
write(0xff);
} else {
write(0);
}
}
/**
* Marshals a DER unsigned integer on the output stream.
*/
public void putInteger(BigInt i) throws IOException {
putUnsignedInteger(i.toByteArray());
}
/**
* Marshals a DER unsigned integer on the output stream.
*/
public void putUnsignedInteger(byte[] integerBytes) throws IOException {
write(DerValue.tag_Integer);
if ((integerBytes[0] & 0x080) != 0) {
/*
* prepend zero so it's not read as a negative number
*/
putLength(integerBytes.length + 1);
write(0);
} else
putLength(integerBytes.length);
write(integerBytes, 0, integerBytes.length);
}
/**
* Marshals a DER enumerated value on the output stream.
*/
public void putEnumerated(int i) throws IOException {
write(DerValue.tag_Enumerated);
int bytemask = 0xff000000;
int signmask = 0x80000000;
int length;
if ((i & 0x80000000) != 0) {
// negative case
for (length = 4; length > 1; --length) {
if ((i & bytemask) != bytemask)
break;
bytemask = bytemask >>> 8;
signmask = signmask >>> 8;
}
if ((i & signmask) == 0) {
// ensure negative case
putLength(length + 1);
write(0xff);
} else {
putLength(length);
}
// unrolled loop
switch (length) {
case 4:
write((byte) (i >>> 24));
case 3:
write((byte) (i >>> 16));
case 2:
write((byte) (i >>> 8));
case 1:
write((byte) i);
}
} else {
// positive case
for (length = 4; length > 1; --length) {
if ((i & bytemask) != 0)
break;
bytemask = bytemask >>> 8;
signmask = signmask >>> 8;
}
if ((i & signmask) != 0) {
// ensure posititive case
putLength(length + 1);
write(0x00);
} else {
putLength(length);
}
// unrolled loop
switch (length) {
case 4:
write((byte) (i >>> 24));
case 3:
write((byte) (i >>> 16));
case 2:
write((byte) (i >>> 8));
case 1:
write((byte) i);
}
}
}
/**
* Marshals a DER bit string on the output stream. The bit
* string must be byte-aligned.
*
* @param bits the bit string, MSB first
*/
public void putBitString(byte[] bits) throws IOException {
write(DerValue.tag_BitString);
putLength(bits.length + 1);
write(0); // all of last octet is used
write(bits);
}
/**
* Converts a boolean array to a BitArray. Trims trailing 0 bits
* in accordance with DER encoding standard. We assume the input is not
* null.
*/
private static BitArray toBitArray(boolean[] bitString) {
if (bitString.length == 0) {
return new BitArray(bitString);
}
// find index of last 1 bit. -1 if there aren't any
int i;
for (i = bitString.length - 1; i >= 0; i--) {
if (bitString[i]) {
break;
}
}
int length = i + 1;
// if length changed, copy to new appropriately-sized array
if (length != bitString.length) {
boolean[] newBitString = new boolean[length];
System.arraycopy(bitString, 0, newBitString, 0, length);
bitString = newBitString;
}
return new BitArray(bitString);
}
/**
* Converts bit string to a BitArray, stripping off trailing 0 bits.
* We assume that the bit string is not null.
*/
private static BitArray toBitArray(byte[] bitString) {
// compute length in bits of bit string
int length, i;
int maxIndex = 0;
if (bitString.length == 0) {
return new BitArray(0, bitString);
}
// find the index of the last byte with a 1 bit
for (i = 0; i < bitString.length; i++) {
if (bitString[i] != 0) {
maxIndex = i;
}
}
byte lastByte = bitString[maxIndex];
length = (maxIndex + 1) * 8; // maximum, might reduce in next step
// now find the last 1 bit in this last byte
for (i = 1; i <= 0x80; i <<= 1) {
if ((lastByte & i) == 0) {
length--;
} else {
break;
}
}
return new BitArray(length, bitString);
}
/**
* Marshals a DER bit string on the output stream.
* The bit strings need not be byte-aligned.
*
* @param ba the bit string, MSB first
*/
public void putUnalignedBitString(BitArray ba) throws IOException {
byte[] bits = ba.toByteArray();
write(DerValue.tag_BitString);
putLength(bits.length + 1);
write(bits.length * 8 - ba.length()); // excess bits in last octet
write(bits);
}
/**
* Marshals a DER bit string on the output stream.
* All trailing 0 bits will be stripped off in accordance with DER
* encoding.
*
* @param bitString the bit string, MSB first
*/
public void putUnalignedBitString(byte[] bitString) throws IOException {
putUnalignedBitString(toBitArray(bitString));
}
/**
* Marshals a DER bit string on the output stream.
* All trailing 0 bits will be stripped off in accordance with DER
* encoding.
*
* @param bitString the bit string as an array of booleans.
*/
public void putUnalignedBitString(boolean[] bitString) throws IOException {
putUnalignedBitString(toBitArray(bitString));
}
/**
* DER-encodes an ASN.1 OCTET STRING value on the output stream.
*
* @param octets the octet string
*/
public void putOctetString(byte[] octets) throws IOException {
write(DerValue.tag_OctetString, octets);
}
/**
* Marshals a DER "null" value on the output stream. These are
* often used to indicate optional values which have been omitted.
*/
public void putNull() throws IOException {
write(DerValue.tag_Null);
putLength(0);
}
/**
* Marshals an object identifier (OID) on the output stream.
* Corresponds to the ASN.1 "OBJECT IDENTIFIER" construct.
*/
public void putOID(ObjectIdentifier oid) throws IOException {
oid.encode(this);
}
/**
* Marshals a sequence on the output stream. This supports both
* the ASN.1 "SEQUENCE" (zero to N values) and "SEQUENCE OF"
* (one to N values) constructs.
*/
public void putSequence(DerValue[] seq) throws IOException {
DerOutputStream bytes = new DerOutputStream();
int i;
for (i = 0; i < seq.length; i++)
seq[i].encode(bytes);
write(DerValue.tag_Sequence, bytes);
}
/**
* Marshals the contents of a set on the output stream without
* ordering the elements. Ok for BER encoding, but not for DER
* encoding.
*
* For DER encoding, use orderedPutSet() or orderedPutSetOf().
*/
public void putSet(DerValue[] set) throws IOException {
DerOutputStream bytes = new DerOutputStream();
int i;
for (i = 0; i < set.length; i++)
set[i].encode(bytes);
write(DerValue.tag_Set, bytes);
}
/**
* NSCP :
* Like putOrderSetOf, except not sorted.
* This may defy DER encoding but is needed for compatibility
* with communicator.
*/
public void putSet(byte tag, DerEncoder[] set) throws IOException {
putOrderedSet(tag, set, null);
}
/**
* Marshals the contents of a set on the output stream. Sets
* are semantically unordered, but DER requires that encodings of
* set elements be sorted into ascending lexicographical order
* before being output. Hence sets with the same tags and
* elements have the same DER encoding.
*
* This method supports the ASN.1 "SET OF" construct, but not
* "SET", which uses a different order.
*/
public void putOrderedSetOf(byte tag, DerEncoder[] set) throws IOException {
putOrderedSet(tag, set, lexOrder);
}
/**
* Marshals the contents of a set on the output stream. Sets
* are semantically unordered, but DER requires that encodings of
* set elements be sorted into ascending tag order
* before being output. Hence sets with the same tags and
* elements have the same DER encoding.
*
* This method supports the ASN.1 "SET" construct, but not
* "SET OF", which uses a different order.
*/
public void putOrderedSet(byte tag, DerEncoder[] set) throws IOException {
putOrderedSet(tag, set, tagOrder);
}
/**
* Lexicographical order comparison on byte arrays, for ordering
* elements of a SET OF objects in DER encoding.
*/
private static ByteArrayLexOrder lexOrder = new ByteArrayLexOrder();
/**
* Tag order comparison on byte arrays, for ordering elements of
* SET objects in DER encoding.
*/
private static ByteArrayTagOrder tagOrder = new ByteArrayTagOrder();
/**
* Marshals a the contents of a set on the output stream with the
* encodings of its sorted in increasing order.
*
* @param order the order to use when sorting encodings of components.
*/
private void putOrderedSet(byte tag, DerEncoder[] set,
Comparator order) throws IOException {
DerOutputStream[] streams = new DerOutputStream[set.length];
for (int i = 0; i < set.length; i++) {
streams[i] = new DerOutputStream();
set[i].derEncode(streams[i]);
}
// order the element encodings
byte[][] bufs = new byte[streams.length][];
for (int i = 0; i < streams.length; i++) {
bufs[i] = streams[i].toByteArray();
}
if (order != null) {
Arrays.sort(bufs, order);
}
DerOutputStream bytes = new DerOutputStream();
for (int i = 0; i < streams.length; i++) {
bytes.write(bufs[i]);
}
write(tag, bytes);
}
/**
* Converts string to printable and writes to der output stream.
*/
public void putPrintableString(String s) throws IOException {
putStringType(DerValue.tag_PrintableString, s);
}
public void putVisibleString(String s) throws IOException {
putStringType(DerValue.tag_VisibleString, s);
}
/**
* Marshals a string which is consists of BMP (unicode) characters
*/
public void putBMPString(String s) throws IOException {
putStringType(DerValue.tag_BMPString, s);
}
public void putGeneralString(String s) throws IOException {
putStringType(DerValue.tag_GeneralString, s);
}
// /*
// * T61 is an 8 bit extension to ASCII, escapes e.g. to Japanese
// */
// void putT61String(String s) throws IOException
// {
// // XXX IMPLEMENT ME
//
// throw new IOException("DerOutputStream.putT61String() NYI");
// }
// /*
// * Universal String.
// */
// void putUniversalString(String s) throws IOException
// {
// // XXX IMPLEMENT ME
//
// throw new IOException("DerOutputStream.putUniversalString() NYI");
// }
/**
* Marshals a string which is consists of IA5(ASCII) characters
*/
public void putIA5String(String s) throws IOException {
putStringType(DerValue.tag_IA5String, s);
}
public void putUTF8String(String s) throws IOException {
putStringType(DerValue.tag_UTF8String, s);
}
public void putStringType(byte tag, String s) throws IOException {
try {
CharsetEncoder encoder = ASN1CharStrConvMap.getDefault().getEncoder(tag);
if (encoder == null)
throw new IOException("No encoder for tag");
CharBuffer charBuffer = CharBuffer.wrap(s.toCharArray());
ByteBuffer byteBuffer = encoder.encode(charBuffer);
write(tag);
putLength(byteBuffer.limit());
write(byteBuffer.array(), byteBuffer.arrayOffset(), byteBuffer.limit());
} catch (CharacterCodingException e) {
throw new IOException("Not a valid string type " + tag, e);
}
}
private void put2DateBytes(byte[] buffer, int value, int offset) {
int upper = value / 10;
int lower = value % 10;
buffer[offset] = (byte) ((byte) upper + (byte) '0');
buffer[offset + 1] = (byte) ((byte) lower + (byte) '0');
}
private Calendar gmtGregorianCalendar = null;
private Calendar getGMTGregorianCalendar() {
if (gmtGregorianCalendar == null) {
TimeZone tz = TimeZone.getTimeZone("GMT");
gmtGregorianCalendar = new GregorianCalendar(tz);
}
return (Calendar) gmtGregorianCalendar.clone();
}
public byte[] getDateBytes(Date d, boolean UTC) {
byte[] datebytes;
if (UTC) {
datebytes = new byte[13];
} else { // generalized time has 4 digits for yr
datebytes = new byte[15];
}
Calendar cal = getGMTGregorianCalendar();
cal.setTime(d);
int i = 0;
if (!UTC) {
put2DateBytes(datebytes, cal.get(Calendar.YEAR) / 100, i);
i += 2;
}
put2DateBytes(datebytes, cal.get(Calendar.YEAR) % 100, i);
// Calendar's MONTH is zero-based
i += 2;
put2DateBytes(datebytes, cal.get(Calendar.MONTH) + 1, i);
i += 2;
put2DateBytes(datebytes, cal.get(Calendar.DAY_OF_MONTH), i);
i += 2;
put2DateBytes(datebytes, cal.get(Calendar.HOUR_OF_DAY), i);
i += 2;
put2DateBytes(datebytes, cal.get(Calendar.MINUTE), i);
i += 2;
put2DateBytes(datebytes, cal.get(Calendar.SECOND), i);
i += 2;
// datebytes[i] = 'Z';
datebytes[i] = (byte) 'Z';
return datebytes;
}
/**
* Marshals a DER UTC time/date value.
*
*
* YYMMDDhhmmss{Z|+hhmm|-hhmm} ... emits only using Zulu time and with seconds (even if seconds=0) as per IETF-PKIX
* partI.
*/
public void putUTCTime(Date d) throws IOException {
/*
* Format the date.
*/
// This was the old code. Way too slow to be usable (stevep)
// String pattern = "yyMMddHHmmss'Z'";
// SimpleDateFormat sdf = new SimpleDateFormat(pattern);
// TimeZone tz = TimeZone.getTimeZone("GMT");
// sdf.setTimeZone(tz);
// byte[] utc = (sdf.format(d)).getBytes();
byte[] datebytes = getDateBytes(d, true); // UTC = true
/*
* Write the formatted date.
*/
write(DerValue.tag_UtcTime);
putLength(datebytes.length);
write(datebytes);
}
/**
* Marshals a DER Generalized Time/date value.
*
*
* YYYYMMDDhhmmss{Z|+hhmm|-hhmm} ... emits only using Zulu time and with seconds (even if seconds=0) as per
* IETF-PKIX partI.
*/
public void putGeneralizedTime(Date d) throws IOException {
/*
* Format the date.
*/
TimeZone tz = TimeZone.getTimeZone("GMT");
// This is way too slow to be usable (stevep)
String pattern = "yyyyMMddHHmmss'Z'";
SimpleDateFormat sdf = new SimpleDateFormat(pattern);
sdf.setTimeZone(tz);
byte[] gt = (sdf.format(d)).getBytes();
/*
* Write the formatted date.
*/
write(DerValue.tag_GeneralizedTime);
putLength(gt.length);
write(gt);
}
/**
* Put the encoding of the length in the stream.
*
* @param len the length of the attribute.
* @exception IOException on writing errors.
*/
public void putLength(int len) throws IOException {
if (len < 128) {
write((byte) len);
} else if (len < (1 << 8)) {
write((byte) 0x081);
write((byte) len);
} else if (len < (1 << 16)) {
write((byte) 0x082);
write((byte) (len >> 8));
write((byte) len);
} else if (len < (1 << 24)) {
write((byte) 0x083);
write((byte) (len >> 16));
write((byte) (len >> 8));
write((byte) len);
} else {
write((byte) 0x084);
write((byte) (len >> 24));
write((byte) (len >> 16));
write((byte) (len >> 8));
write((byte) len);
}
}
/**
* Put the tag of the attribute in the stream.
*
* @param tagClass the tag class type, one of UNIVERSAL, CONTEXT,
* APPLICATION or PRIVATE
* @param form if true, the value is constructed, otherwise it is
* primitive.
* @param val the tag value
*/
public void putTag(byte tagClass, boolean form, byte val) {
byte tag = (byte) (tagClass | val);
if (form) {
tag |= (byte) 0x20;
}
write(tag);
}
/**
* Write the current contents of this DerOutputStream
to an OutputStream
.
*
* @exception IOException on output error.
*/
@Override
public void derEncode(OutputStream out) throws IOException {
out.write(toByteArray());
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/util/DerValue.java 0000664 0000000 0000000 00000056774 14565430767 0027767 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.util;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.CharsetDecoder;
import java.util.Arrays;
import org.mozilla.jss.netscape.security.x509.AVAValueConverter;
import org.mozilla.jss.netscape.security.x509.GenericValueConverter;
/**
* Represents a single DER-encoded value. DER encoding rules are a subset
* of the "Basic" Encoding Rules (BER), but they only support a single way
* ("Definite" encoding) to encode any given value.
*
*
* All DER-encoded data are triples {type, length, data}. This class represents such tagged values as they have
* been read (or constructed), and provides structured access to the encoded data.
*
*
* At this time, this class supports only a subset of the types of DER data encodings which are defined. That subset is
* sufficient for parsing most X.509 certificates, and working with selected additional formats (such as PKCS #10
* certificate requests, and some kinds of PKCS #7 data).
*
* @version 1.43
*
* @author David Brownell
* @author Amit Kapoor
* @author Hemma Prafullchandra
*/
public class DerValue {
/** The tag class types */
public static final byte TAG_UNIVERSAL = (byte) 0x000;
public static final byte TAG_APPLICATION = (byte) 0x040;
public static final byte TAG_CONTEXT = (byte) 0x080;
public static final byte TAG_PRIVATE = (byte) 0x0c0;
/** The DER tag of the value; one of the tag_ constants. */
public byte tag;
protected DerInputBuffer buffer;
/**
* The DER-encoded data of the value.
*/
public DerInputStream data;
private int length;
/*
* The type starts at the first byte of the encoding, and
* is one of these tag_* values. That may be all the type
* data that is needed.
*/
/*
* These tags are the "universal" tags ... they mean the same
* in all contexts. (Mask with 0x1f -- five bits.)
*/
/** Tag value indicating an ASN.1 "BOOLEAN" value. */
public final static byte tag_Boolean = 0x01;
/** Tag value indicating an ASN.1 "INTEGER" value. */
public final static byte tag_Integer = 0x02;
/** Tag value indicating an ASN.1 "BIT STRING" value. */
public final static byte tag_BitString = 0x03;
/** Tag value indicating an ASN.1 "OCTET STRING" value. */
public final static byte tag_OctetString = 0x04;
/** Tag value indicating an ASN.1 "NULL" value. */
public final static byte tag_Null = 0x05;
/** Tag value indicating an ASN.1 "OBJECT IDENTIFIER" value. */
public final static byte tag_ObjectId = 0x06;
/** Tag value including an ASN.1 "ENUMERATED" value */
public final static byte tag_Enumerated = 0x0A;
/** Tag value including a "printable" string */
public final static byte tag_PrintableString = 0x13;
public final static byte tag_VisibleString = 0x1A;
/** Tag value including a "teletype" string */
public final static byte tag_T61String = 0x14;
/** Tag value including an ASCII string */
public final static byte tag_IA5String = 0x16;
/** Tag value indicating an ASN.1 "UTCTime" value. */
public final static byte tag_UtcTime = 0x17;
/** Tag value indicating an ASN.1 "GeneralizedTime" value. */
public final static byte tag_GeneralizedTime = 0x18;
/** Tag value indicating an ASN.1 "GeneralString" value. */
public final static byte tag_GeneralString = 0x1B;
/** Tag value indicating an ASN.1 "BMPString" value. */
public final static byte tag_BMPString = 0x1E;
/** Tag value indicating an ASN.1 "UniversalString" value. */
public final static byte tag_UniversalString = 0x1C;
/** Tag value indicating an ASN.1 "UTF8String" value. (since 1998) */
public final static byte tag_UTF8String = 0x0C;
public final static byte[] tags_DirectoryString =
{ tag_T61String
, tag_PrintableString
, tag_UniversalString
, tag_UTF8String
, tag_BMPString };
// CONSTRUCTED seq/set
/**
* Tag value indicating an ASN.1
* "SEQUENCE" (zero to N elements, order is significant).
*/
public final static byte tag_Sequence = 0x30;
/**
* Tag value indicating an ASN.1
* "SEQUENCE OF" (one to N elements, order is significant).
*/
public final static byte tag_SequenceOf = 0x30;
/**
* Tag value indicating an ASN.1
* "SET" (zero to N members, order does not matter).
*/
public final static byte tag_Set = 0x31;
/**
* Tag value indicating an ASN.1
* "SET OF" (one to N members, order does not matter).
*/
public final static byte tag_SetOf = 0x31;
/*
* These values are the high order bits for the other kinds of tags.
*/
boolean isUniversal() {
return ((tag & 0x0c0) == 0x000);
}
boolean isApplication() {
return ((tag & 0x0c0) == 0x040);
}
/**
* Returns true iff the CONTEXT SPECIFIC bit is set in the type tag.
* This is associated with the ASN.1 "DEFINED BY" syntax.
*/
public boolean isContextSpecific() {
return ((tag & 0x0c0) == 0x080);
}
/**
* Returns true iff the CONTEXT SPECIFIC TAG matches the passed tag.
*/
public boolean isContextSpecific(byte cntxtTag) {
if (!isContextSpecific()) {
return false;
}
return ((tag & 0x01f) == cntxtTag);
}
boolean isPrivate() {
return ((tag & 0x0c0) == 0x0c0);
}
/** Returns true iff the CONSTRUCTED bit is set in the type tag. */
public boolean isConstructed() {
return ((tag & 0x020) == 0x020);
}
/**
* Creates a DER value from a string
* using a generic way of determining the proper tag for the string.
* Assumes the string is a Generic attribute value and uses
* the converter for generic string values to convert to the Der Value.
*/
public DerValue(String value)
throws IOException {
AVAValueConverter genericValue = new GenericValueConverter();
DerValue val;
val = genericValue.getValue(value);
tag = val.tag;
buffer = val.buffer;
length = val.length;
data = val.data;
data.mark(Integer.MAX_VALUE);
}
/**
* Creates a DerValue from a tag and some DER-encoded data.
*
* @param tag the DER type tag
* @param data the DER-encoded data
*/
public DerValue(byte tag, byte[] data) {
this.tag = tag;
buffer = new DerInputBuffer(data.clone());
length = data.length;
this.data = new DerInputStream(buffer);
this.data.mark(Integer.MAX_VALUE);
}
/**
* Creates a DerValue from a tag and some DER-encoded data.
*
* @param tag the DER type tag
* @param data the DER-encoded data
* @param offset offset of the data
* @param length length of the data
*/
public DerValue(byte tag, byte[] data, int offset, int length) {
this(tag, Arrays.copyOfRange(data, offset, offset + length));
}
/*
* package private
*/
DerValue(DerInputBuffer in) throws IOException {
// NOTE: This must handle the special value used
// to terminate BER indefinite encodings (tag and
// length are both zero)
// XXX must also parse BER-encoded constructed
// values such as sequences, sets...
tag = (byte) in.read();
length = DerInputStream.getLength(in);
buffer = in.dup();
buffer.truncate(length);
data = new DerInputStream(buffer);
in.skip(length);
}
/**
* Get an ASN.1/DER encoded datum from a buffer. The
* entire buffer must hold exactly one datum, including
* its tag and length.
*
* @param buf buffer holding a single DER-encoded datum.
*/
public DerValue(byte[] buf) throws IOException {
init(true, new ByteArrayInputStream(buf));
}
/**
* Get an ASN.1/DER encoded datum from part of a buffer.
* That part of the buffer must hold exactly one datum, including
* its tag and length.
*
* @param buf the buffer
* @param offset start point of the single DER-encoded dataum
* @param len how many bytes are in the encoded datum
*/
public DerValue(byte[] buf, int offset, int len) throws IOException {
init(true, new ByteArrayInputStream(buf, offset, len));
}
/**
* Get an ASN1/DER encoded datum from an input stream. The
* stream may have additional data following the encoded datum.
*
* @param in the input stream holding a single DER datum,
* which may be followed by additional data
*/
public DerValue(InputStream in) throws IOException {
init(false, in);
}
/*
* helper routine
*/
private void init(boolean fullyBuffered, InputStream in)
throws IOException {
byte[] bytes;
tag = (byte) in.read();
length = DerInputStream.getLength(in);
if (fullyBuffered && in.available() != length)
throw new IOException("extra DER value data (constructor)");
bytes = new byte[length];
// n.b. readFully not needed in normal fullyBuffered case
DataInputStream dis = new DataInputStream(in);
dis.readFully(bytes);
buffer = new DerInputBuffer(bytes);
data = new DerInputStream(buffer);
}
/**
* Encode an ASN1/DER encoded datum onto a DER output stream.
*/
public void encode(DerOutputStream out)
throws IOException {
out.write(tag);
out.putLength(length);
buffer.dump(out, length);
}
/**
* Returns an ASN.1 BOOLEAN
*
* @return the boolean held in this DER value
*/
public boolean getBoolean() throws IOException {
if (tag != tag_Boolean) {
throw new IOException("DerValue.getBoolean, not a BOOLEAN " + tag);
}
if (length != 1) {
throw new IOException("DerValue.getBoolean, invalid length " + length);
}
if (buffer.read() != 0) {
return true;
}
return false;
}
/**
* Returns an ASN.1 OBJECT IDENTIFIER.
*
* @return the OID held in this DER value
*/
public ObjectIdentifier getOID() throws IOException {
if (tag != tag_ObjectId)
throw new IOException("DerValue.getOID, not an OID " + tag);
return new ObjectIdentifier(buffer);
}
/**
* Returns an ASN.1 OCTET STRING
*
* @return the octet string held in this DER value
*/
public byte[] getOctetString() throws IOException {
if (tag != tag_OctetString)
throw new IOException(
"DerValue.getOctetString, not an Octet String: " + tag);
byte[] bytes = new byte[length];
int n = buffer.read(bytes);
if (n != length && !(n == -1 && length == 0)) {
/* We read less (or more, somehow?) than expected.
*
* The second condition handles a corner case: when
* ByteArrayInputStream has no more data, read returns -1, even if
* are asking to read 0 bytes. This seems to violate the contract
* of the superclass InputStream.read() which says that if the
* requested read length is 0, the return value is 0. So we have
* to treat a return value of (-1) as acceptable iff the length is
* zero.
*/
throw new IOException(
"getOctetString: short read on DerValue buffer: "
+ "expected to read " + length + " bytes; "
+ "actually read " + n + " bytes.");
}
return bytes;
}
/**
* Returns an ASN.1 unsigned integer value of enumerated value.
*
* @return the (unsigned) integer held in this DER value
*/
public int getEnumerated()
throws IOException {
if (tag != tag_Enumerated)
throw new IOException("DerValue.getEnumerated, not an ENUMERATED " + tag);
if (length == 0)
return 0;
if (length > 4 || length < 1)
throw new IOException("DerValue.getEnumerated, invalid length " + length + "(must be between 1 and 4)");
int value = 0;
int nextbyte = buffer.read();
if (nextbyte == -1)
throw new IOException("short read on DerValue buffer");
// perform sign extension
value = (byte) nextbyte;
for (int i = length - 1; i > 0; --i) {
nextbyte = buffer.read();
if (nextbyte == -1)
throw new IOException("short read on DerValue buffer");
value = 256 * value + nextbyte;
}
return value;
}
/**
* Returns an ASN.1 unsigned INTEGER value.
*
* @return the (unsigned) integer held in this DER value
*/
public BigInt getInteger() throws IOException {
if (tag != tag_Integer)
throw new IOException("DerValue.getInteger, not an int " + tag);
return buffer.getUnsigned(data.available());
}
/**
* Returns an ASN.1 unsigned INTEGER value, the parameter determining
* if the tag is implicit.
*
* @param tagImplicit if true, ignores the tag value as it is
* assumed implicit.
* @return the (unsigned) integer held in this DER value
*/
public BigInt getInteger(boolean tagImplicit) throws IOException {
if (!tagImplicit) {
if (tag != tag_Integer) {
throw new IOException("DerValue.getInteger, not an int "
+ tag);
}
}
return buffer.getUnsigned(data.available());
}
/**
* Returns an ASN.1 BIT STRING value. The bit string must be byte-aligned.
*
* @return the bit string held in this value
*/
public byte[] getBitString() throws IOException {
if (tag != tag_BitString)
throw new IOException(
"DerValue.getBitString, not a bit string " + tag);
return buffer.getBitString();
}
/**
* Returns an ASN.1 BIT STRING value that need not be byte-aligned.
*
* @return a BitArray representing the bit string held in this value
*/
public BitArray getUnalignedBitString() throws IOException {
if (tag != tag_BitString)
throw new IOException(
"DerValue.getBitString, not a bit string " + tag);
return buffer.getUnalignedBitString();
}
/**
* Returns the name component as a Java string, regardless of its
* encoding restrictions (ASCII, T61, Printable, etc).
*/
public String getAsString() throws IOException {
AVAValueConverter genericValue = new GenericValueConverter();
return genericValue.getAsString(this);
}
/**
* Returns an ASN.1 BIT STRING value, with the tag assumed implicit
* based on the parameter. The bit string must be byte-aligned.
*
* @param tagImplicit if true, the tag is assumed implicit.
* @return the bit string held in this value
*/
public byte[] getBitString(boolean tagImplicit) throws IOException {
if (!tagImplicit) {
if (tag != tag_BitString)
throw new IOException("DerValue.getBitString, not a bit string "
+ tag);
}
return buffer.getBitString();
}
/**
* Returns an ASN.1 BIT STRING value, with the tag assumed implicit
* based on the parameter. The bit string need not be byte-aligned.
*
* @param tagImplicit if true, the tag is assumed implicit.
* @return the bit string held in this value
*/
public BitArray getUnalignedBitString(boolean tagImplicit)
throws IOException {
if (!tagImplicit) {
if (tag != tag_BitString)
throw new IOException("DerValue.getBitString, not a bit string "
+ tag);
}
return buffer.getUnalignedBitString();
}
/**
* Returns an ASN.1 STRING value
*
* @return the printable string held in this value
*/
public String getPrintableString()
throws IOException {
if (tag != tag_PrintableString)
throw new IOException(
"DerValue.getPrintableString, not a string " + tag);
return getASN1CharString();
}
public String getDirectoryString() throws IOException {
boolean tagValid = false;
for (int i = 0; i < tags_DirectoryString.length; i++) {
if (tag == tags_DirectoryString[i]) {
tagValid = true;
break;
}
}
if (!tagValid)
throw new IOException(
"DerValue.getDirectoryString: invalid tag: " + tag);
return getASN1CharString();
}
/*
* @eturns a string if the DerValue is a ASN.1 character string type and
* if there is a decoder for the type. Returns null otherwise.
*/
public String getASN1CharString() throws IOException {
try {
CharsetDecoder decoder = ASN1CharStrConvMap.getDefault().getDecoder(tag);
if (decoder == null)
return null;
ByteBuffer byteBuffer = ByteBuffer.allocate(length);
data.reset();
data.getBytes(byteBuffer.array());
CharBuffer charBuffer = decoder.decode(byteBuffer);
return charBuffer.toString();
} catch (CharacterCodingException e) {
throw new IOException("Misformed DER value", e);
}
}
/**
* Returns an ASN.1 T61 (Teletype) STRING value
*
* @return the teletype string held in this value
*/
public String getT61String() throws IOException {
if (tag != tag_T61String)
throw new IOException(
"DerValue.getT61String, not T61 " + tag);
return getASN1CharString();
}
/**
* Returns an ASN.1 IA5 (ASCII) STRING value
*
* @return the ASCII string held in this value
*/
public String getIA5String() throws IOException {
if (tag != tag_IA5String)
throw new IOException(
"DerValue.getIA5String, not IA5 " + tag);
return getASN1CharString();
}
public String getBMPString()
throws IOException {
if (tag != tag_BMPString)
throw new IOException(
"DerValue.getBMPString, not BMP " + tag);
return getASN1CharString();
}
public String getUniversalString()
throws IOException {
if (tag != tag_UniversalString)
throw new IOException(
"DerValue.getUniversalString, not UniversalString " + tag);
return getASN1CharString();
}
public String getUTF8String()
throws IOException {
if (tag != tag_UTF8String)
throw new IOException(
"DerValue.getUTF8String, not UTF8String " + tag);
return getASN1CharString();
}
/**
* Returns true iff the other object is a DER value which
* is bitwise equal to this one.
*
* @param other the object being compared with this one
*/
@Override
public boolean equals(Object other) {
if (other instanceof DerValue)
return equals((DerValue) other);
else
return false;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((buffer == null) ? 0 : buffer.hashCode());
result = prime * result + ((data == null) ? 0 : data.hashCode());
result = prime * result + length;
result = prime * result + tag;
return result;
}
/**
* Bitwise equality comparison. DER encoded values have a single
* encoding, so that bitwise equality of the encoded values is an
* efficient way to establish equivalence of the unencoded values.
*
* @param other the object being compared with this one
*/
public boolean equals(DerValue other) {
data.reset();
other.data.reset();
if (this == other)
return true;
else if (tag != other.tag) {
return false;
} else {
return buffer.equals(other.buffer);
}
}
/**
* Returns a printable representation of the value.
*
* @return printable representation of the value
*/
@Override
public String toString() {
try {
String s = getAsString();
if (s != null)
return s;
if (tag == tag_Null)
return "[DerValue, null]";
if (tag == tag_ObjectId)
return "OID." + getOID();
// integers
else
return "[DerValue, tag = " + tag
+ ", length = " + length + "]";
} catch (IOException e) {
throw new IllegalArgumentException("misformatted DER value");
}
}
/**
* Returns a DER-encoded value, such that if it's passed to the
* DerValue constructor, a value equivalent to "this" is returned.
*
* @return DER-encoded value, including tag and length.
*/
public byte[] toByteArray() throws IOException {
DerOutputStream out = new DerOutputStream();
encode(out);
data.reset();
return out.toByteArray();
}
/**
* For "set" and "sequence" types, this function may be used
* to return a DER stream of the members of the set or sequence.
* This operation is not supported for primitive types such as
* integers or bit strings.
*/
public DerInputStream toDerInputStream() throws IOException {
if (tag == tag_Sequence || tag == tag_Set)
return new DerInputStream(buffer);
throw new IOException("toDerInputStream rejects tag type " + tag);
}
/**
* Get the length of the encoded value.
*/
public int length() {
return length;
}
/**
* Create the tag of the attribute.
*
* @param tagClass the tag class type, one of UNIVERSAL, CONTEXT,
* APPLICATION or PRIVATE
* @param form if true, the value is constructed, otherwise it
* is primitive.
* @param val the tag value
*/
public static byte createTag(byte tagClass, boolean form, byte val) {
byte tag = (byte) (tagClass | val);
if (form) {
tag |= (byte) 0x20;
}
return (tag);
}
/**
* Set the tag of the attribute. Commonly used to reset the
* tag value used for IMPLICIT encodings.
*
* @param tag the tag value
*/
public void resetTag(byte tag) {
this.tag = tag;
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/util/ExtPrettyPrint.java 0000664 0000000 0000000 00000212220 14565430767 0031221 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.util;
import java.io.IOException;
import java.math.BigInteger;
import java.security.cert.CertificateException;
import java.text.DateFormat;
import java.util.Enumeration;
import java.util.ResourceBundle;
import java.util.Vector;
import org.mozilla.jss.netscape.security.extensions.AccessDescription;
import org.mozilla.jss.netscape.security.extensions.AuthInfoAccessExtension;
import org.mozilla.jss.netscape.security.extensions.CertificateScopeEntry;
import org.mozilla.jss.netscape.security.extensions.CertificateScopeOfUseExtension;
import org.mozilla.jss.netscape.security.extensions.ExtendedKeyUsageExtension;
import org.mozilla.jss.netscape.security.extensions.InhibitAnyPolicyExtension;
import org.mozilla.jss.netscape.security.extensions.NSCertTypeExtension;
import org.mozilla.jss.netscape.security.extensions.OCSPNoCheckExtension;
import org.mozilla.jss.netscape.security.extensions.PresenceServerExtension;
import org.mozilla.jss.netscape.security.extensions.SubjectInfoAccessExtension;
import org.mozilla.jss.netscape.security.x509.Attribute;
import org.mozilla.jss.netscape.security.x509.AuthorityKeyIdentifierExtension;
import org.mozilla.jss.netscape.security.x509.BasicConstraintsExtension;
import org.mozilla.jss.netscape.security.x509.CPSuri;
import org.mozilla.jss.netscape.security.x509.CRLDistributionPoint;
import org.mozilla.jss.netscape.security.x509.CRLDistributionPointsExtension;
import org.mozilla.jss.netscape.security.x509.CRLDistributionPointsExtension.Reason;
import org.mozilla.jss.netscape.security.x509.CRLNumberExtension;
import org.mozilla.jss.netscape.security.x509.CRLReasonExtension;
import org.mozilla.jss.netscape.security.x509.CertificateIssuerExtension;
import org.mozilla.jss.netscape.security.x509.CertificatePoliciesExtension;
import org.mozilla.jss.netscape.security.x509.CertificatePolicyInfo;
import org.mozilla.jss.netscape.security.x509.CertificatePolicyMap;
import org.mozilla.jss.netscape.security.x509.DeltaCRLIndicatorExtension;
import org.mozilla.jss.netscape.security.x509.DisplayText;
import org.mozilla.jss.netscape.security.x509.Extension;
import org.mozilla.jss.netscape.security.x509.FreshestCRLExtension;
import org.mozilla.jss.netscape.security.x509.GeneralName;
import org.mozilla.jss.netscape.security.x509.GeneralNameInterface;
import org.mozilla.jss.netscape.security.x509.GeneralNames;
import org.mozilla.jss.netscape.security.x509.HoldInstructionExtension;
import org.mozilla.jss.netscape.security.x509.InvalidityDateExtension;
import org.mozilla.jss.netscape.security.x509.IssuerAlternativeNameExtension;
import org.mozilla.jss.netscape.security.x509.IssuingDistributionPoint;
import org.mozilla.jss.netscape.security.x509.IssuingDistributionPointExtension;
import org.mozilla.jss.netscape.security.x509.KeyIdentifier;
import org.mozilla.jss.netscape.security.x509.KeyUsageExtension;
import org.mozilla.jss.netscape.security.x509.NSCCommentExtension;
import org.mozilla.jss.netscape.security.x509.NameConstraintsExtension;
import org.mozilla.jss.netscape.security.x509.NoticeReference;
import org.mozilla.jss.netscape.security.x509.OIDMap;
import org.mozilla.jss.netscape.security.x509.PolicyConstraintsExtension;
import org.mozilla.jss.netscape.security.x509.PolicyMappingsExtension;
import org.mozilla.jss.netscape.security.x509.PolicyQualifierInfo;
import org.mozilla.jss.netscape.security.x509.PolicyQualifiers;
import org.mozilla.jss.netscape.security.x509.PrivateKeyUsageExtension;
import org.mozilla.jss.netscape.security.x509.Qualifier;
import org.mozilla.jss.netscape.security.x509.RDN;
import org.mozilla.jss.netscape.security.x509.SerialNumber;
import org.mozilla.jss.netscape.security.x509.SubjectAlternativeNameExtension;
import org.mozilla.jss.netscape.security.x509.SubjectDirAttributesExtension;
import org.mozilla.jss.netscape.security.x509.SubjectKeyIdentifierExtension;
import org.mozilla.jss.netscape.security.x509.UserNotice;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This class will display the certificate content in predefined
* format.
*
* @author Andrew Wnuk
* @version $Revision$, $Date$
*/
public class ExtPrettyPrint {
private static final Logger logger = LoggerFactory.getLogger(ExtPrettyPrint.class);
/*==========================================================
* variables
*==========================================================*/
private Extension mExt = null;
private ResourceBundle mResource = null;
private PrettyPrintFormat pp = null;
private int mIndentSize = 0;
DateFormat dateFormater = null;
/*==========================================================
* constructors
*==========================================================*/
public ExtPrettyPrint(Extension ext, int indentSize) {
mExt = ext;
mResource = ResourceBundle.getBundle(PrettyPrintResources.class.getName());
mIndentSize = indentSize;
pp = new PrettyPrintFormat(":");
}
/*==========================================================
* public methods
*==========================================================*/
/**
* This method return string representation of the certificate
* in predefined format using specified client local. I18N Support.
*
* @return string representation of the certificate
*/
@Override
public String toString() {
StringBuffer sb = new StringBuffer();
//check if the extension is known
if (mExt instanceof KeyUsageExtension) {
return getKeyUsage();
}
if (mExt instanceof NSCertTypeExtension) {
return getCertType();
}
if (mExt instanceof AuthorityKeyIdentifierExtension) {
return getAuthorityKeyIdentifier();
}
if (mExt instanceof SubjectKeyIdentifierExtension) {
return getSubjectKeyIdentifier();
}
if (mExt instanceof CRLReasonExtension) {
return getCRLReasonExtension();
}
if (mExt instanceof BasicConstraintsExtension) {
return getBasicConstraintsExtension();
}
if (mExt instanceof NSCCommentExtension) {
return getNSCCommentExtension();
}
if (mExt instanceof NameConstraintsExtension) {
return getNameConstraintsExtension();
}
if (mExt instanceof CRLNumberExtension) {
return getCRLNumberExtension();
}
if (mExt instanceof DeltaCRLIndicatorExtension) {
return getDeltaCRLIndicatorExtension();
}
if (mExt instanceof IssuerAlternativeNameExtension) {
return getIssuerAlternativeNameExtension();
}
if (mExt instanceof SubjectAlternativeNameExtension) {
return getSubjectAlternativeNameExtension();
}
if (mExt instanceof FreshestCRLExtension) {
return getFreshestCRLExtension();
}
if (mExt instanceof CRLDistributionPointsExtension) {
return getCRLDistributionPointsExtension();
}
if (mExt instanceof IssuingDistributionPointExtension) {
return getIssuingDistributionPointExtension();
}
if (mExt instanceof ExtendedKeyUsageExtension) {
return getExtendedKeyUsageExtension();
}
if (mExt instanceof AuthInfoAccessExtension) {
return getAuthInfoAccessExtension();
}
if (mExt instanceof SubjectInfoAccessExtension) {
return getSubjectInfoAccessExtension();
}
if (mExt instanceof OCSPNoCheckExtension) {
return getOCSPNoCheckExtension();
}
if (mExt instanceof PrivateKeyUsageExtension) {
return getPrivateKeyUsageExtension();
}
if (mExt instanceof InvalidityDateExtension) {
return getInvalidityDateExtension();
}
if (mExt instanceof CertificateIssuerExtension) {
return getCertificateIssuerExtension();
}
if (mExt instanceof HoldInstructionExtension) {
return getHoldInstructionExtension();
}
if (mExt instanceof PolicyConstraintsExtension) {
return getPolicyConstraintsExtension();
}
if (mExt instanceof PolicyMappingsExtension) {
return getPolicyMappingsExtension();
}
if (mExt instanceof SubjectDirAttributesExtension) {
return getSubjectDirAttributesExtension();
}
if (mExt instanceof CertificateScopeOfUseExtension) {
return getCertificateScopeOfUseExtension();
}
if (mExt instanceof PresenceServerExtension) {
return getPresenceServerExtension();
}
if (mExt instanceof InhibitAnyPolicyExtension) {
return getInhibitAnyPolicyExtension();
}
if (mExt instanceof CertificatePoliciesExtension) {
return getCertificatePoliciesExtension();
}
//unknown cert extension
String extName = OIDMap.getName(mExt.getExtensionId());
if (extName == null)
sb.append(pp.indent(mIndentSize) + mResource.getString(
PrettyPrintResources.TOKEN_IDENTIFIER) +
mExt.getExtensionId().toString() + "\n");
else
sb.append(pp.indent(mIndentSize) + mResource.getString(
PrettyPrintResources.TOKEN_IDENTIFIER) + " " + extName + " - " +
mExt.getExtensionId().toString() + "\n");
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(
PrettyPrintResources.TOKEN_CRITICAL));
if (mExt.isCritical()) {
sb.append(mResource.getString(
PrettyPrintResources.TOKEN_YES) + "\n");
} else {
sb.append(mResource.getString(
PrettyPrintResources.TOKEN_NO) + "\n");
}
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(
PrettyPrintResources.TOKEN_VALUE) + "\n");
sb.append(pp.toHexString(mExt.getExtensionValue(), mIndentSize + 8, 16));
return sb.toString();
}
/*==========================================================
* Private methods
*==========================================================*/
private String getNSCCommentExtension() {
StringBuffer sb = new StringBuffer();
sb.append(pp.indent(mIndentSize) + mResource.getString(
PrettyPrintResources.TOKEN_IDENTIFIER));
sb.append(mResource.getString(PrettyPrintResources.TOKEN_NSC_COMMENT) +
"- " + mExt.getExtensionId().toString() + "\n");
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(
PrettyPrintResources.TOKEN_CRITICAL));
if (mExt.isCritical()) {
sb.append(mResource.getString(
PrettyPrintResources.TOKEN_YES) + "\n");
} else {
sb.append(mResource.getString(
PrettyPrintResources.TOKEN_NO) + "\n");
}
sb.append(pp.indent(mIndentSize + 4) + ((NSCCommentExtension) mExt).toPrint(mIndentSize) + "\n");
return sb.toString();
}
private String getNameConstraintsExtension() {
StringBuffer sb = new StringBuffer();
sb.append(pp.indent(mIndentSize) + mResource.getString(
PrettyPrintResources.TOKEN_IDENTIFIER));
sb.append(mResource.getString(PrettyPrintResources.TOKEN_NAME_CONSTRAINTS) +
"- " + mExt.getExtensionId().toString() + "\n");
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(
PrettyPrintResources.TOKEN_CRITICAL));
if (mExt.isCritical()) {
sb.append(mResource.getString(
PrettyPrintResources.TOKEN_YES) + "\n");
} else {
sb.append(mResource.getString(
PrettyPrintResources.TOKEN_NO) + "\n");
}
sb.append(pp.indent(mIndentSize + 4) + ((NameConstraintsExtension) mExt).toPrint(mIndentSize + 4));
return sb.toString();
}
private String getOCSPNoCheckExtension() {
StringBuffer sb = new StringBuffer();
sb.append(pp.indent(mIndentSize) + mResource.getString(
PrettyPrintResources.TOKEN_IDENTIFIER));
sb.append(mResource.getString(PrettyPrintResources.TOKEN_OCSP_NOCHECK) +
"- " + mExt.getExtensionId().toString() + "\n");
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(
PrettyPrintResources.TOKEN_CRITICAL));
if (mExt.isCritical()) {
sb.append(mResource.getString(
PrettyPrintResources.TOKEN_YES) + "\n");
} else {
sb.append(mResource.getString(
PrettyPrintResources.TOKEN_NO) + "\n");
}
return sb.toString();
}
private String getSubjectInfoAccessExtension() {
StringBuffer sb = new StringBuffer();
sb.append(pp.indent(mIndentSize) + mResource.getString(
PrettyPrintResources.TOKEN_IDENTIFIER));
sb.append(mResource.getString(PrettyPrintResources.TOKEN_SIA) +
"- " + mExt.getExtensionId().toString() + "\n");
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(
PrettyPrintResources.TOKEN_CRITICAL));
if (mExt.isCritical()) {
sb.append(mResource.getString(
PrettyPrintResources.TOKEN_YES) + "\n");
} else {
sb.append(mResource.getString(
PrettyPrintResources.TOKEN_NO) + "\n");
}
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(
PrettyPrintResources.TOKEN_ACCESS_DESC) + "\n");
SubjectInfoAccessExtension aia = (SubjectInfoAccessExtension) mExt;
for (int i = 0; i < aia.numberOfAccessDescription(); i++) {
AccessDescription ad = aia.getAccessDescription(i);
ObjectIdentifier method = ad.getMethod();
if (method.equals(SubjectInfoAccessExtension.METHOD_OCSP)) {
sb.append(pp.indent(mIndentSize + 8) + "Method #" + i + ": " +
"ocsp" + "\n");
} else {
sb.append(pp.indent(mIndentSize + 8) + "Method #" + i + ": " +
method.toString() + "\n");
}
sb.append(pp.indent(mIndentSize + 8) + "Location #" + i + ": " +
ad.getLocation().toString() + "\n");
}
return sb.toString();
}
private String getAuthInfoAccessExtension() {
StringBuffer sb = new StringBuffer();
sb.append(pp.indent(mIndentSize) + mResource.getString(
PrettyPrintResources.TOKEN_IDENTIFIER));
sb.append(mResource.getString(PrettyPrintResources.TOKEN_AIA) +
"- " + mExt.getExtensionId().toString() + "\n");
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(
PrettyPrintResources.TOKEN_CRITICAL));
if (mExt.isCritical()) {
sb.append(mResource.getString(
PrettyPrintResources.TOKEN_YES) + "\n");
} else {
sb.append(mResource.getString(
PrettyPrintResources.TOKEN_NO) + "\n");
}
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(
PrettyPrintResources.TOKEN_ACCESS_DESC) + "\n");
AuthInfoAccessExtension aia = (AuthInfoAccessExtension) mExt;
for (int i = 0; i < aia.numberOfAccessDescription(); i++) {
AccessDescription ad = aia.getAccessDescription(i);
ObjectIdentifier method = ad.getMethod();
if (method.equals(AuthInfoAccessExtension.METHOD_OCSP)) {
sb.append(pp.indent(mIndentSize + 8) + "Method #" + i + ": " +
"ocsp" + "\n");
} else {
sb.append(pp.indent(mIndentSize + 8) + "Method #" + i + ": " +
method.toString() + "\n");
}
sb.append(pp.indent(mIndentSize + 8) + "Location #" + i + ": " +
ad.getLocation().toString() + "\n");
}
return sb.toString();
}
private String getPresenceServerExtension() {
StringBuffer sb = new StringBuffer();
sb.append(pp.indent(mIndentSize) + mResource.getString(
PrettyPrintResources.TOKEN_IDENTIFIER));
sb.append(mResource.getString(PrettyPrintResources.TOKEN_PRESENCE_SERVER) +
"- " + mExt.getExtensionId().toString() + "\n");
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(
PrettyPrintResources.TOKEN_CRITICAL));
if (mExt.isCritical()) {
sb.append(mResource.getString(
PrettyPrintResources.TOKEN_YES) + "\n");
} else {
sb.append(mResource.getString(
PrettyPrintResources.TOKEN_NO) + "\n");
}
PresenceServerExtension pse = (PresenceServerExtension) mExt;
sb.append(pp.indent(mIndentSize + 4) + "Version : " + pse.getVersion() + "\n");
sb.append(pp.indent(mIndentSize + 4) + "Street Address : " + pse.getStreetAddress() + "\n");
sb.append(pp.indent(mIndentSize + 4) + "Telephone Number : " + pse.getTelephoneNumber() + "\n");
sb.append(pp.indent(mIndentSize + 4) + "RFC822 Name : " + pse.getRFC822() + "\n");
sb.append(pp.indent(mIndentSize + 4) + "ID : " + pse.getID() + "\n");
sb.append(pp.indent(mIndentSize + 4) + "Host Name : " + pse.getHostName() + "\n");
sb.append(pp.indent(mIndentSize + 4) + "Port Number : " + pse.getPortNumber() + "\n");
sb.append(pp.indent(mIndentSize + 4) + "Max Users : " + pse.getMaxUsers() + "\n");
sb.append(pp.indent(mIndentSize + 4) + "Service Level : " + pse.getServiceLevel() + "\n");
return sb.toString();
}
private String getPrivateKeyUsageExtension() {
StringBuffer sb = new StringBuffer();
sb.append(pp.indent(mIndentSize) + mResource.getString(
PrettyPrintResources.TOKEN_IDENTIFIER));
sb.append(mResource.getString(PrettyPrintResources.TOKEN_PRIVATE_KEY_USAGE) +
"- " + mExt.getExtensionId().toString() + "\n");
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(
PrettyPrintResources.TOKEN_CRITICAL));
if (mExt.isCritical()) {
sb.append(mResource.getString(
PrettyPrintResources.TOKEN_YES) + "\n");
} else {
sb.append(mResource.getString(
PrettyPrintResources.TOKEN_NO) + "\n");
}
PrivateKeyUsageExtension usage = (PrivateKeyUsageExtension) mExt;
sb.append(pp.indent(mIndentSize + 4) + "Validity:\n");
if (dateFormater == null) {
dateFormater = DateFormat.getDateInstance(DateFormat.FULL);
}
String notBefore = dateFormater.format(usage.getNotBefore());
String notAfter = dateFormater.format(usage.getNotAfter());
sb.append(pp.indent(mIndentSize + 8) + "Not Before: " + notBefore + "\n");
sb.append(pp.indent(mIndentSize + 8) + "Not After: " + notAfter + "\n");
return sb.toString();
}
private String getExtendedKeyUsageExtension() {
StringBuffer sb = new StringBuffer();
sb.append(pp.indent(mIndentSize) + mResource.getString(
PrettyPrintResources.TOKEN_IDENTIFIER));
sb.append(mResource.getString(PrettyPrintResources.TOKEN_EXTENDED_KEY_USAGE) +
"- " + mExt.getExtensionId().toString() + "\n");
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(
PrettyPrintResources.TOKEN_CRITICAL));
if (mExt.isCritical()) {
sb.append(mResource.getString(
PrettyPrintResources.TOKEN_YES) + "\n");
} else {
sb.append(mResource.getString(
PrettyPrintResources.TOKEN_NO) + "\n");
}
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(
PrettyPrintResources.TOKEN_EXTENDED_KEY_USAGE) + "\n");
ExtendedKeyUsageExtension usage = (ExtendedKeyUsageExtension) mExt;
Enumeration e = usage.getOIDs();
if (e != null) {
while (e.hasMoreElements()) {
ObjectIdentifier oid = e.nextElement();
if (oid.equals(ExtendedKeyUsageExtension.OID_OCSP_SIGNING)) {
sb.append(pp.indent(mIndentSize + 8) + "OCSPSigning" + "\n");
} else {
sb.append(pp.indent(mIndentSize + 8) + oid.toString() + "\n");
}
}
}
return sb.toString();
}
/**
* String Representation of KeyUsageExtension
*/
private String getKeyUsage() {
StringBuffer sb = new StringBuffer();
try {
sb.append(pp.indent(mIndentSize) + mResource.getString(
PrettyPrintResources.TOKEN_IDENTIFIER));
sb.append(mResource.getString(PrettyPrintResources.TOKEN_KEY_USAGE) +
"- " + mExt.getExtensionId().toString() + "\n");
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(
PrettyPrintResources.TOKEN_CRITICAL));
if (mExt.isCritical()) {
sb.append(mResource.getString(
PrettyPrintResources.TOKEN_YES) + "\n");
} else {
sb.append(mResource.getString(
PrettyPrintResources.TOKEN_NO) + "\n");
}
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(
PrettyPrintResources.TOKEN_KEY_USAGE) + "\n");
KeyUsageExtension usage = (KeyUsageExtension) mExt;
if (((Boolean) usage.get(KeyUsageExtension.DIGITAL_SIGNATURE)).booleanValue()) {
sb.append(pp.indent(mIndentSize + 8) + mResource.getString(KeyUsageExtension.DIGITAL_SIGNATURE) + "\n");
}
if (((Boolean) usage.get(KeyUsageExtension.NON_REPUDIATION)).booleanValue()) {
sb.append(pp.indent(mIndentSize + 8) + mResource.getString(KeyUsageExtension.NON_REPUDIATION) + "\n");
}
if (((Boolean) usage.get(KeyUsageExtension.KEY_ENCIPHERMENT)).booleanValue()) {
sb.append(pp.indent(mIndentSize + 8) + mResource.getString(KeyUsageExtension.KEY_ENCIPHERMENT) + "\n");
}
if (((Boolean) usage.get(KeyUsageExtension.DATA_ENCIPHERMENT)).booleanValue()) {
sb.append(pp.indent(mIndentSize + 8) + mResource.getString(KeyUsageExtension.DATA_ENCIPHERMENT) + "\n");
}
if (((Boolean) usage.get(KeyUsageExtension.KEY_AGREEMENT)).booleanValue()) {
sb.append(pp.indent(mIndentSize + 8) + mResource.getString(KeyUsageExtension.KEY_AGREEMENT) + "\n");
}
if (((Boolean) usage.get(KeyUsageExtension.KEY_CERTSIGN)).booleanValue()) {
sb.append(pp.indent(mIndentSize + 8) + mResource.getString(KeyUsageExtension.KEY_CERTSIGN) + "\n");
}
if (((Boolean) usage.get(KeyUsageExtension.CRL_SIGN)).booleanValue()) {
sb.append(pp.indent(mIndentSize + 8) + mResource.getString(KeyUsageExtension.CRL_SIGN) + "\n");
}
if (((Boolean) usage.get(KeyUsageExtension.ENCIPHER_ONLY)).booleanValue()) {
sb.append(pp.indent(mIndentSize + 8) + mResource.getString(KeyUsageExtension.ENCIPHER_ONLY) + "\n");
}
if (((Boolean) usage.get(KeyUsageExtension.DECIPHER_ONLY)).booleanValue()) {
sb.append(pp.indent(mIndentSize + 8) + mResource.getString(KeyUsageExtension.DECIPHER_ONLY) + "\n");
}
return sb.toString();
} catch (IOException e) {
logger.debug("Problem getting key usage", e);
return sb.toString();
}
}
/**
* String Representation of NSCertTypeExtension
*/
private String getCertType() {
StringBuffer sb = new StringBuffer();
try {
sb.append(pp.indent(mIndentSize) + mResource.getString(PrettyPrintResources.TOKEN_IDENTIFIER));
sb.append(mResource.getString(PrettyPrintResources.TOKEN_CERT_TYPE)
+ "- " + mExt.getExtensionId().toString() + "\n");
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_CRITICAL));
if (mExt.isCritical()) {
sb.append(mResource.getString(PrettyPrintResources.TOKEN_YES) + "\n");
} else {
sb.append(mResource.getString(PrettyPrintResources.TOKEN_NO) + "\n");
}
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_CERT_USAGE) + "\n");
NSCertTypeExtension type = (NSCertTypeExtension) mExt;
if (((Boolean) type.get(NSCertTypeExtension.SSL_CLIENT)).booleanValue()) {
sb.append(pp.indent(mIndentSize + 8) + mResource.getString(NSCertTypeExtension.SSL_CLIENT) + "\n");
}
if (((Boolean) type.get(NSCertTypeExtension.SSL_SERVER)).booleanValue()) {
sb.append(pp.indent(mIndentSize + 8) + mResource.getString(NSCertTypeExtension.SSL_SERVER) + "\n");
}
if (((Boolean) type.get(NSCertTypeExtension.EMAIL)).booleanValue()) {
sb.append(pp.indent(mIndentSize + 8) + mResource.getString(NSCertTypeExtension.EMAIL) + "\n");
}
if (((Boolean) type.get(NSCertTypeExtension.OBJECT_SIGNING)).booleanValue()) {
sb.append(pp.indent(mIndentSize + 8) + mResource.getString(NSCertTypeExtension.OBJECT_SIGNING) + "\n");
}
if (((Boolean) type.get(NSCertTypeExtension.SSL_CA)).booleanValue()) {
sb.append(pp.indent(mIndentSize + 8) + mResource.getString(NSCertTypeExtension.SSL_CA) + "\n");
}
if (((Boolean) type.get(NSCertTypeExtension.EMAIL_CA)).booleanValue()) {
sb.append(pp.indent(mIndentSize + 8) + mResource.getString(NSCertTypeExtension.EMAIL_CA) + "\n");
}
if (((Boolean) type.get(NSCertTypeExtension.OBJECT_SIGNING_CA)).booleanValue()) {
sb.append(pp.indent(mIndentSize + 8)
+ mResource.getString(NSCertTypeExtension.OBJECT_SIGNING_CA) + "\n");
}
return sb.toString();
} catch (CertificateException e) {
logger.debug("Problem getting certificate type", e);
return "";
}
}
/**
* String Representation of SubjectKeyIdentifierExtension
*/
private String getSubjectKeyIdentifier() {
StringBuffer sb = new StringBuffer();
try {
sb.append(pp.indent(mIndentSize) + mResource.getString(PrettyPrintResources.TOKEN_IDENTIFIER));
sb.append(mResource.getString(PrettyPrintResources.TOKEN_SKI)
+ "- " + mExt.getExtensionId().toString() + "\n");
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_CRITICAL));
if (mExt.isCritical()) {
sb.append(mResource.getString(PrettyPrintResources.TOKEN_YES) + "\n");
} else {
sb.append(mResource.getString(PrettyPrintResources.TOKEN_NO) + "\n");
}
SubjectKeyIdentifierExtension id = (SubjectKeyIdentifierExtension) mExt;
KeyIdentifier keyId = (KeyIdentifier) id.get(SubjectKeyIdentifierExtension.KEY_ID);
if (keyId != null) {
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_KEY_ID) + "\n");
sb.append(pp.toHexString(keyId.getIdentifier(), 24, 16));
}
return sb.toString();
} catch (IOException e) {
logger.debug("Problem getting subject identifier", e);
return "";
}
}
/**
* String Representation of AuthorityKeyIdentifierExtension
*/
private String getAuthorityKeyIdentifier() {
StringBuffer sb = new StringBuffer();
try {
sb.append(pp.indent(mIndentSize) + mResource.getString(PrettyPrintResources.TOKEN_IDENTIFIER));
sb.append(mResource.getString(PrettyPrintResources.TOKEN_AKI)
+ "- " + mExt.getExtensionId().toString() + "\n");
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_CRITICAL));
if (mExt.isCritical()) {
sb.append(mResource.getString(PrettyPrintResources.TOKEN_YES) + "\n");
} else {
sb.append(mResource.getString(PrettyPrintResources.TOKEN_NO) + "\n");
}
AuthorityKeyIdentifierExtension id = (AuthorityKeyIdentifierExtension) mExt;
KeyIdentifier keyId = (KeyIdentifier) id.get(AuthorityKeyIdentifierExtension.KEY_ID);
if (keyId != null) {
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_KEY_ID) + "\n");
sb.append(pp.toHexString(keyId.getIdentifier(), mIndentSize + 8, 16));
// sb.append(pp.toHexString(keyId.getIdentifier(),24,16));
}
GeneralNames authNames = (GeneralNames) id.get(AuthorityKeyIdentifierExtension.AUTH_NAME);
if (authNames != null) {
for (int i = 0; i < authNames.size(); i++) {
GeneralName authName = (GeneralName) authNames.elementAt(i);
if (authName != null) {
sb.append(pp.indent(mIndentSize + 4)
+ mResource.getString(PrettyPrintResources.TOKEN_AUTH_NAME) + authName.toString()
+ "\n");
}
}
}
SerialNumber serial = (SerialNumber) id.get(AuthorityKeyIdentifierExtension.SERIAL_NUMBER);
if (serial != null) {
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_SERIAL) +
"0x" + serial.getNumber().toBigInteger().toString(16).toUpperCase() + "\n");
}
return sb.toString();
} catch (IOException e) {
logger.debug("Problem getting authority key identifier", e);
return "";
}
}
/**
* String Representation of CRLReasonExtension
*/
private String getCRLReasonExtension() {
StringBuffer sb = new StringBuffer();
try {
sb.append(pp.indent(mIndentSize) + mResource.getString(PrettyPrintResources.TOKEN_IDENTIFIER));
sb.append(mResource.getString(PrettyPrintResources.TOKEN_REVOCATION_REASON) + "- " +
mExt.getExtensionId().toString() + "\n");
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_CRITICAL));
CRLReasonExtension ext = (CRLReasonExtension) mExt;
if (mExt.isCritical()) {
sb.append(mResource.getString(PrettyPrintResources.TOKEN_YES) + "\n");
} else {
sb.append(mResource.getString(PrettyPrintResources.TOKEN_NO) + "\n");
}
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_REASON) +
ext.getReason().toString() + "\n");
return sb.toString();
} catch (Exception e) {
return "";
}
}
/**
* String Representation of InhibitAnyPolicyExtension
*/
private String getInhibitAnyPolicyExtension() {
StringBuffer sb = new StringBuffer();
sb.append(pp.indent(mIndentSize) +
mResource.getString(PrettyPrintResources.TOKEN_IDENTIFIER));
sb.append(mResource.getString(
PrettyPrintResources.TOKEN_INHIBIT_ANY_POLICY_EXT) + "- " +
mExt.getExtensionId().toString() + "\n");
sb.append(pp.indent(mIndentSize + 4) +
mResource.getString(PrettyPrintResources.TOKEN_CRITICAL));
InhibitAnyPolicyExtension ext = (InhibitAnyPolicyExtension) mExt;
if (mExt.isCritical())
sb.append(mResource.getString(
PrettyPrintResources.TOKEN_YES) + "\n");
else
sb.append(mResource.getString(
PrettyPrintResources.TOKEN_NO) + "\n");
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(
PrettyPrintResources.TOKEN_SKIP_CERTS));
BigInt num = ext.getSkipCerts();
sb.append("" + num.toInt() + "\n");
return sb.toString();
}
/**
* String Representation of BasicConstraintsExtension
*/
private String getBasicConstraintsExtension() {
StringBuffer sb = new StringBuffer();
try {
sb.append(pp.indent(mIndentSize) + mResource.getString(PrettyPrintResources.TOKEN_IDENTIFIER));
sb.append(mResource.getString(PrettyPrintResources.TOKEN_BASIC_CONSTRAINTS) + "- " +
mExt.getExtensionId().toString() + "\n");
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_CRITICAL));
BasicConstraintsExtension ext = (BasicConstraintsExtension) mExt;
if (mExt.isCritical()) {
sb.append(mResource.getString(PrettyPrintResources.TOKEN_YES) + "\n");
} else {
sb.append(mResource.getString(PrettyPrintResources.TOKEN_NO) + "\n");
}
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_IS_CA));
boolean isCA = ((Boolean) ext.get(BasicConstraintsExtension.IS_CA)).booleanValue();
if (isCA) {
sb.append(mResource.getString(PrettyPrintResources.TOKEN_YES) + "\n");
} else {
sb.append(mResource.getString(PrettyPrintResources.TOKEN_NO) + "\n");
}
Integer pathLength = (Integer) ext.get(BasicConstraintsExtension.PATH_LEN);
if (pathLength != null) {
if (pathLength.longValue() >= 0) {
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_PATH_LEN) +
pathLength.toString() + "\n");
} else if (pathLength.longValue() == -1 || pathLength.longValue() == -2) {
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_PATH_LEN) +
mResource.getString(PrettyPrintResources.TOKEN_PATH_LEN_UNLIMITED) + "\n");
} else {
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_PATH_LEN) +
mResource.getString(PrettyPrintResources.TOKEN_PATH_LEN_INVALID) +
" (" + pathLength.toString() + ")\n");
}
}
return sb.toString();
} catch (IOException e) {
logger.debug("Problem getting basic constraints", e);
return "";
}
}
/**
* String Representation of CRLNumberExtension
*/
private String getCRLNumberExtension() {
StringBuffer sb = new StringBuffer();
try {
sb.append(pp.indent(mIndentSize) + mResource.getString(PrettyPrintResources.TOKEN_IDENTIFIER));
sb.append(mResource.getString(PrettyPrintResources.TOKEN_CRL_NUMBER) + "- " +
mExt.getExtensionId().toString() + "\n");
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_CRITICAL));
CRLNumberExtension ext = (CRLNumberExtension) mExt;
if (mExt.isCritical()) {
sb.append(mResource.getString(PrettyPrintResources.TOKEN_YES) + "\n");
} else {
sb.append(mResource.getString(PrettyPrintResources.TOKEN_NO) + "\n");
}
BigInteger crlNumber = (BigInteger) ext.get(CRLNumberExtension.NUMBER);
if (crlNumber != null) {
sb.append(pp.indent(mIndentSize + 4) +
mResource.getString(PrettyPrintResources.TOKEN_NUMBER) +
crlNumber.toString() + "\n");
}
return sb.toString();
} catch (IOException e) {
logger.debug("Problem getting CRL number extensions", e);
return "";
}
}
/**
* String Representation of DeltaCRLIndicatorExtension
*/
private String getDeltaCRLIndicatorExtension() {
StringBuffer sb = new StringBuffer();
try {
sb.append(pp.indent(mIndentSize) + mResource.getString(PrettyPrintResources.TOKEN_IDENTIFIER));
sb.append(mResource.getString(PrettyPrintResources.TOKEN_DELTA_CRL_INDICATOR) + "- " +
mExt.getExtensionId().toString() + "\n");
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_CRITICAL));
DeltaCRLIndicatorExtension ext = (DeltaCRLIndicatorExtension) mExt;
if (mExt.isCritical()) {
sb.append(mResource.getString(PrettyPrintResources.TOKEN_YES) + "\n");
} else {
sb.append(mResource.getString(PrettyPrintResources.TOKEN_NO) + "\n");
}
BigInteger crlNumber = (BigInteger) ext.get(DeltaCRLIndicatorExtension.NUMBER);
if (crlNumber != null) {
sb.append(pp.indent(mIndentSize + 4) +
mResource.getString(PrettyPrintResources.TOKEN_BASE_CRL_NUMBER) +
crlNumber.toString() + "\n");
}
return sb.toString();
} catch (IOException e) {
logger.debug("Problem getting delta CRL extensions", e);
return "";
}
}
/**
* String Representation of IssuerAlternativeName Extension
*/
private String getIssuerAlternativeNameExtension() {
StringBuffer sb = new StringBuffer();
try {
sb.append(pp.indent(mIndentSize) + mResource.getString(PrettyPrintResources.TOKEN_IDENTIFIER));
sb.append(mResource.getString(PrettyPrintResources.TOKEN_ISSUER_ALT_NAME) + "- " +
mExt.getExtensionId().toString() + "\n");
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_CRITICAL));
IssuerAlternativeNameExtension ext = (IssuerAlternativeNameExtension) mExt;
if (mExt.isCritical()) {
sb.append(mResource.getString(PrettyPrintResources.TOKEN_YES) + "\n");
} else {
sb.append(mResource.getString(PrettyPrintResources.TOKEN_NO) + "\n");
}
GeneralNames issuerNames = (GeneralNames) ext.get(IssuerAlternativeNameExtension.ISSUER_NAME);
if (issuerNames != null) {
sb.append(pp.indent(mIndentSize + 4) +
mResource.getString(PrettyPrintResources.TOKEN_ISSUER_NAMES) + "\n");
for (int i = 0; i < issuerNames.size(); i++) {
GeneralName issuerName = (GeneralName) issuerNames.elementAt(i);
if (issuerName != null) {
String nameType = "";
if (issuerName.getType() == GeneralNameInterface.NAME_DIRECTORY)
nameType = "DirectoryName: ";
sb.append(pp.indent(mIndentSize + 8) + nameType + issuerName.toString() + "\n");
}
}
}
return sb.toString();
} catch (IOException e) {
return "";
}
}
/**
* String Representation of SubjectAlternativeName Extension
*/
private String getSubjectAlternativeNameExtension() {
StringBuffer sb = new StringBuffer();
try {
sb.append(pp.indent(mIndentSize) + mResource.getString(PrettyPrintResources.TOKEN_IDENTIFIER));
sb.append(mResource.getString(PrettyPrintResources.TOKEN_SUBJECT_ALT_NAME) + "- " +
mExt.getExtensionId().toString() + "\n");
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_CRITICAL));
SubjectAlternativeNameExtension ext = (SubjectAlternativeNameExtension) mExt;
if (mExt.isCritical()) {
sb.append(mResource.getString(PrettyPrintResources.TOKEN_YES) + "\n");
} else {
sb.append(mResource.getString(PrettyPrintResources.TOKEN_NO) + "\n");
}
GeneralNames subjectNames = (GeneralNames) ext.get(SubjectAlternativeNameExtension.SUBJECT_NAME);
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_VALUE) + "\n");
for (int i = 0; i < subjectNames.size(); i++) {
GeneralName subjectName = (GeneralName) subjectNames.elementAt(i);
if (subjectName != null) {
String nameType = "";
if (subjectName.getType() == GeneralNameInterface.NAME_DIRECTORY)
nameType = "DirectoryName: ";
sb.append(pp.indent(mIndentSize + 8) + nameType + subjectName.toString() + "\n");
}
}
return sb.toString();
} catch (IOException e) {
logger.debug("Problem getting subject alternative name", e);
return "";
}
}
/**
* String Representation of CertificateScopeOfUse Extension
*/
private String getCertificateScopeOfUseExtension() {
StringBuffer sb = new StringBuffer();
sb.append(pp.indent(mIndentSize) + mResource.getString(PrettyPrintResources.TOKEN_IDENTIFIER));
sb.append(mResource.getString(PrettyPrintResources.TOKEN_CERT_SCOPE_OF_USE) + "- " +
mExt.getExtensionId().toString() + "\n");
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_CRITICAL));
CertificateScopeOfUseExtension ext = (CertificateScopeOfUseExtension) mExt;
if (mExt.isCritical()) {
sb.append(mResource.getString(PrettyPrintResources.TOKEN_YES) + "\n");
} else {
sb.append(mResource.getString(PrettyPrintResources.TOKEN_NO) + "\n");
}
Vector entries = ext.getCertificateScopeEntries();
if (entries != null) {
sb.append(pp.indent(mIndentSize + 4) +
mResource.getString(PrettyPrintResources.TOKEN_SCOPE_OF_USE) + "\n");
for (int i = 0; i < entries.size(); i++) {
CertificateScopeEntry se = entries.elementAt(i);
GeneralName gn = se.getGeneralName();
if (gn != null) {
String nameType = "";
if (gn.getType() == GeneralNameInterface.NAME_DIRECTORY)
nameType = "DirectoryName: ";
sb.append(pp.indent(mIndentSize + 8) + nameType + gn.toString() + "\n");
}
BigInt port = se.getPort();
if (port != null) {
sb.append(pp.indent(mIndentSize + 8) + PrettyPrintResources.TOKEN_PORT +
port.toBigInteger().toString() + "\n");
}
}
}
return sb.toString();
}
/**
* String Representation of FreshestCRLExtension
*/
private String getFreshestCRLExtension() {
StringBuffer sb = new StringBuffer();
//
// Generic stuff: name, OID, criticality
//
sb.append(pp.indent(mIndentSize) +
mResource.getString(PrettyPrintResources.TOKEN_IDENTIFIER));
sb.append(mResource.getString(
PrettyPrintResources.TOKEN_FRESHEST_CRL_EXT) + "- " +
mExt.getExtensionId().toString() + "\n");
sb.append(pp.indent(mIndentSize + 4) +
mResource.getString(PrettyPrintResources.TOKEN_CRITICAL));
if (mExt.isCritical()) {
sb.append(mResource.getString(
PrettyPrintResources.TOKEN_YES) + "\n");
} else {
sb.append(mResource.getString(
PrettyPrintResources.TOKEN_NO) + "\n");
}
//
// Now the CRLDP-specific stuff
//
FreshestCRLExtension ext = (FreshestCRLExtension) mExt;
int numPoints = ext.getNumPoints();
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(
PrettyPrintResources.TOKEN_CRLDP_NUMPOINTS)
+ numPoints + "\n");
for (int i = 0; i < numPoints; i++) {
//
// print one individual CRL distribution point
//
int idt;
idt = mIndentSize + 4; // reset each time through loop
boolean isEmpty = true;
sb.append(pp.indent(idt) +
mResource.getString(PrettyPrintResources.TOKEN_CRLDP_POINTN) +
i + "\n");
CRLDistributionPoint pt = ext.getPointAt(i);
idt += 4; // further indent rest of information
if (pt.getFullName() != null) {
isEmpty = false;
sb.append(pp.indent(idt) +
mResource.getString(PrettyPrintResources.TOKEN_CRLDP_DISTPOINT)
+ pt.getFullName() + "\n");
}
if (pt.getRelativeName() != null) {
isEmpty = false;
sb.append(pp.indent(idt) +
mResource.getString(PrettyPrintResources.TOKEN_CRLDP_DISTPOINT)
+ pt.getRelativeName() + "\n");
}
if (pt.getReasons() != null) {
isEmpty = false;
byte[] reasonBits = pt.getReasons().toByteArray();
String reasonList = reasonBitsToReasonList(reasonBits);
sb.append(pp.indent(idt) +
mResource.getString(PrettyPrintResources.TOKEN_CRLDP_REASONS)
+ reasonList + "\n");
}
if (pt.getCRLIssuer() != null) {
isEmpty = false;
sb.append(pp.indent(idt) +
mResource.getString(PrettyPrintResources.TOKEN_CRLDP_CRLISSUER)
+ pt.getCRLIssuer() + "\n");
}
if (isEmpty) {
sb.append(pp.indent(idt) + "empty\n");
}
}
return sb.toString();
}
/**
* String Representation of CRLDistributionPointsExtension
*/
private String getCRLDistributionPointsExtension() {
StringBuffer sb = new StringBuffer();
//
// Generic stuff: name, OID, criticality
//
sb.append(pp.indent(mIndentSize) +
mResource.getString(PrettyPrintResources.TOKEN_IDENTIFIER));
sb.append(mResource.getString(
PrettyPrintResources.TOKEN_CRL_DP_EXT) + "- " +
mExt.getExtensionId().toString() + "\n");
sb.append(pp.indent(mIndentSize + 4) +
mResource.getString(PrettyPrintResources.TOKEN_CRITICAL));
if (mExt.isCritical()) {
sb.append(mResource.getString(
PrettyPrintResources.TOKEN_YES) + "\n");
} else {
sb.append(mResource.getString(
PrettyPrintResources.TOKEN_NO) + "\n");
}
//
// Now the CRLDP-specific stuff
//
CRLDistributionPointsExtension ext =
(CRLDistributionPointsExtension) mExt;
int numPoints = ext.getNumPoints();
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(
PrettyPrintResources.TOKEN_CRLDP_NUMPOINTS)
+ numPoints + "\n");
for (int i = 0; i < numPoints; i++) {
//
// print one individual CRL distribution point
//
int idt;
idt = mIndentSize + 4; // reset each time through loop
boolean isEmpty = true;
sb.append(pp.indent(idt) +
mResource.getString(PrettyPrintResources.TOKEN_CRLDP_POINTN) +
i + "\n");
CRLDistributionPoint pt = ext.getPointAt(i);
idt += 4; // further indent rest of information
if (pt.getFullName() != null) {
isEmpty = false;
sb.append(pp.indent(idt) +
mResource.getString(PrettyPrintResources.TOKEN_CRLDP_DISTPOINT)
+ pt.getFullName() + "\n");
}
if (pt.getRelativeName() != null) {
isEmpty = false;
sb.append(pp.indent(idt) +
mResource.getString(PrettyPrintResources.TOKEN_CRLDP_DISTPOINT)
+ pt.getRelativeName() + "\n");
}
if (pt.getReasons() != null) {
isEmpty = false;
byte[] reasonBits = pt.getReasons().toByteArray();
String reasonList = reasonBitsToReasonList(reasonBits);
sb.append(pp.indent(idt) +
mResource.getString(PrettyPrintResources.TOKEN_CRLDP_REASONS)
+ reasonList + "\n");
}
if (pt.getCRLIssuer() != null) {
isEmpty = false;
sb.append(pp.indent(idt) +
mResource.getString(PrettyPrintResources.TOKEN_CRLDP_CRLISSUER)
+ pt.getCRLIssuer() + "\n");
}
if (isEmpty) {
sb.append(pp.indent(idt) + "empty\n");
}
}
return sb.toString();
}
private static String reasonBitsToReasonList(byte[] reasonBits) {
Reason[] reasons = Reason.bitArrayToReasonArray(reasonBits);
if (reasons.length == 0) {
return "";
} else {
StringBuffer buf = new StringBuffer();
buf.append(reasons[0].getName());
for (int i = 1; i < reasons.length; i++) {
buf.append(", ");
buf.append(reasons[i].getName());
}
return buf.toString();
}
}
/**
* String Representation of IssuerAlternativeName Extension
*/
private String getIssuingDistributionPointExtension() {
StringBuffer sb = new StringBuffer();
sb.append(pp.indent(mIndentSize) + mResource.getString(PrettyPrintResources.TOKEN_IDENTIFIER));
sb.append(mResource.getString(PrettyPrintResources.TOKEN_ISSUING_DIST_POINT) + "- " +
mExt.getExtensionId().toString() + "\n");
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_CRITICAL));
if (mExt.isCritical()) {
sb.append(mResource.getString(PrettyPrintResources.TOKEN_YES) + "\n");
} else {
sb.append(mResource.getString(PrettyPrintResources.TOKEN_NO) + "\n");
}
IssuingDistributionPointExtension ext = (IssuingDistributionPointExtension) mExt;
IssuingDistributionPoint issuingDistributionPoint = ext.getIssuingDistributionPoint();
if (issuingDistributionPoint != null) {
GeneralNames fullNames = issuingDistributionPoint.getFullName();
RDN relativeName = issuingDistributionPoint.getRelativeName();
if (fullNames != null || relativeName != null) {
sb.append(pp.indent(mIndentSize + 4)
+ mResource.getString(PrettyPrintResources.TOKEN_DIST_POINT_NAME) + "\n");
if (fullNames != null) {
sb.append(pp.indent(mIndentSize + 8)
+ mResource.getString(PrettyPrintResources.TOKEN_FULL_NAME) + "\n");
for (int i = 0; i < fullNames.size(); i++) {
GeneralName fullName = (GeneralName) fullNames.elementAt(i);
if (fullName != null) {
sb.append(pp.indent(mIndentSize + 12) + fullName.toString() + "\n");
}
}
}
if (relativeName != null) {
sb.append(pp.indent(mIndentSize + 8)
+ mResource.getString(PrettyPrintResources.TOKEN_RELATIVE_NAME) +
relativeName.toString() + "\n");
}
}
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_ONLY_USER_CERTS));
if (issuingDistributionPoint.getOnlyContainsUserCerts()) {
sb.append(mResource.getString(PrettyPrintResources.TOKEN_YES) + "\n");
} else {
sb.append(mResource.getString(PrettyPrintResources.TOKEN_NO) + "\n");
}
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_ONLY_CA_CERTS));
if (issuingDistributionPoint.getOnlyContainsCACerts()) {
sb.append(mResource.getString(PrettyPrintResources.TOKEN_YES) + "\n");
} else {
sb.append(mResource.getString(PrettyPrintResources.TOKEN_NO) + "\n");
}
BitArray onlySomeReasons = issuingDistributionPoint.getOnlySomeReasons();
if (onlySomeReasons != null) {
sb.append(pp.indent(mIndentSize + 4)
+ mResource.getString(PrettyPrintResources.TOKEN_ONLY_SOME_REASONS));
sb.append("0x" + pp.toHexString(onlySomeReasons.toByteArray()));
}
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(PrettyPrintResources.TOKEN_INDIRECT_CRL));
if (issuingDistributionPoint.getIndirectCRL()) {
sb.append(mResource.getString(PrettyPrintResources.TOKEN_YES) + "\n");
} else {
sb.append(mResource.getString(PrettyPrintResources.TOKEN_NO) + "\n");
}
}
return sb.toString();
}
/**
* String Representation of InvalidityDateExtension
*/
private String getInvalidityDateExtension() {
StringBuffer sb = new StringBuffer();
sb.append(pp.indent(mIndentSize) + mResource.getString(
PrettyPrintResources.TOKEN_IDENTIFIER));
sb.append(mResource.getString(PrettyPrintResources.TOKEN_INVALIDITY_DATE) +
"- " + mExt.getExtensionId().toString() + "\n");
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(
PrettyPrintResources.TOKEN_CRITICAL));
InvalidityDateExtension ext = (InvalidityDateExtension) mExt;
if (mExt.isCritical()) {
sb.append(mResource.getString(PrettyPrintResources.TOKEN_YES) + "\n");
} else {
sb.append(mResource.getString(PrettyPrintResources.TOKEN_NO) + "\n");
}
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(
PrettyPrintResources.TOKEN_DATE_OF_INVALIDITY) +
ext.getInvalidityDate().toString() + "\n");
return sb.toString();
}
/**
* String Representation of CertificateIssuerExtension
*/
private String getCertificateIssuerExtension() {
StringBuffer sb = new StringBuffer();
try {
sb.append(pp.indent(mIndentSize) + mResource.getString(
PrettyPrintResources.TOKEN_IDENTIFIER));
sb.append(mResource.getString(PrettyPrintResources.TOKEN_CERTIFICATE_ISSUER) +
"- " + mExt.getExtensionId().toString() + "\n");
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(
PrettyPrintResources.TOKEN_CRITICAL));
CertificateIssuerExtension ext = (CertificateIssuerExtension) mExt;
if (mExt.isCritical()) {
sb.append(mResource.getString(PrettyPrintResources.TOKEN_YES) + "\n");
} else {
sb.append(mResource.getString(PrettyPrintResources.TOKEN_NO) + "\n");
}
GeneralNames issuerNames = (GeneralNames) ext.get(
CertificateIssuerExtension.CERTIFICATE_ISSUER);
if (issuerNames != null) {
sb.append(pp.indent(mIndentSize + 4) +
mResource.getString(PrettyPrintResources.TOKEN_ISSUER_NAMES) + "\n");
for (int i = 0; i < issuerNames.size(); i++) {
GeneralName issuerName = (GeneralName) issuerNames.elementAt(i);
if (issuerName != null) {
String nameType = "";
if (issuerName.getType() == GeneralNameInterface.NAME_DIRECTORY)
nameType = "DirectoryName: ";
sb.append(pp.indent(mIndentSize + 8) + nameType + issuerName.toString() + "\n");
}
}
}
return sb.toString();
} catch (IOException e) {
logger.debug("Problem getting certificate issuer", e);
return "";
}
}
/**
* String Representation of HoldInstructionExtension
*/
private String getHoldInstructionExtension() {
StringBuffer sb = new StringBuffer();
sb.append(pp.indent(mIndentSize) + mResource.getString(
PrettyPrintResources.TOKEN_IDENTIFIER));
sb.append(mResource.getString(PrettyPrintResources.TOKEN_HOLD_INSTRUCTION) +
"- " + mExt.getExtensionId().toString() + "\n");
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(
PrettyPrintResources.TOKEN_CRITICAL));
HoldInstructionExtension ext = (HoldInstructionExtension) mExt;
if (mExt.isCritical()) {
sb.append(mResource.getString(PrettyPrintResources.TOKEN_YES) + "\n");
} else {
sb.append(mResource.getString(PrettyPrintResources.TOKEN_NO) + "\n");
}
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(
PrettyPrintResources.TOKEN_HOLD_INSTRUCTION_CODE) +
ext.getHoldInstructionCodeDescription() + "\n");
return sb.toString();
}
/**
* String Representation of PolicyConstraintsExtension
*/
private String getPolicyConstraintsExtension() {
StringBuffer sb = new StringBuffer();
sb.append(pp.indent(mIndentSize) + mResource.getString(
PrettyPrintResources.TOKEN_IDENTIFIER));
sb.append(
mResource.getString(
PrettyPrintResources.TOKEN_POLICY_CONSTRAINTS) +
"- " + mExt.getExtensionId().toString() + "\n");
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(
PrettyPrintResources.TOKEN_CRITICAL));
if (mExt.isCritical()) {
sb.append(mResource.getString(PrettyPrintResources.TOKEN_YES) + "\n");
} else {
sb.append(mResource.getString(PrettyPrintResources.TOKEN_NO) + "\n");
}
PolicyConstraintsExtension ext = (PolicyConstraintsExtension) mExt;
int require = ext.getRequireExplicitMapping();
int inhibit = ext.getInhibitPolicyMapping();
sb.append(
pp.indent(mIndentSize + 4) +
mResource.getString(
PrettyPrintResources.TOKEN_REQUIRE_EXPLICIT_POLICY) +
((require == -1) ?
mResource.getString(PrettyPrintResources.TOKEN_NOT_SET) :
String.valueOf(require)) + "\n");
sb.append(
pp.indent(mIndentSize + 4) +
mResource.getString(
PrettyPrintResources.TOKEN_INHIBIT_POLICY_MAPPING) +
((inhibit == -1) ?
mResource.getString(PrettyPrintResources.TOKEN_NOT_SET) :
String.valueOf(inhibit)) + "\n");
return sb.toString();
}
/**
* String Representation of PolicyMappingsExtension
*/
private String getPolicyMappingsExtension() {
StringBuffer sb = new StringBuffer();
sb.append(pp.indent(mIndentSize) + mResource.getString(
PrettyPrintResources.TOKEN_IDENTIFIER));
sb.append(mResource.getString(PrettyPrintResources.TOKEN_POLICY_MAPPINGS) +
"- " + mExt.getExtensionId().toString() + "\n");
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(
PrettyPrintResources.TOKEN_CRITICAL));
if (mExt.isCritical()) {
sb.append(mResource.getString(PrettyPrintResources.TOKEN_YES) + "\n");
} else {
sb.append(mResource.getString(PrettyPrintResources.TOKEN_NO) + "\n");
}
PolicyMappingsExtension ext = (PolicyMappingsExtension) mExt;
Enumeration maps = ext.getMappings();
sb.append(pp.indent(mIndentSize + 4) +
mResource.getString(PrettyPrintResources.TOKEN_MAPPINGS));
if (maps == null || !maps.hasMoreElements()) {
sb.append(
mResource.getString(PrettyPrintResources.TOKEN_NONE) + "\n");
} else {
sb.append("\n");
for (int i = 0; maps.hasMoreElements(); i++) {
sb.append(pp.indent(mIndentSize + 8) +
mResource.getString(
PrettyPrintResources.TOKEN_MAP) + i + ":" + "\n");
CertificatePolicyMap m =
maps.nextElement();
sb.append(pp.indent(mIndentSize + 12) +
mResource.getString(
PrettyPrintResources.TOKEN_ISSUER_DOMAIN_POLICY) +
m.getIssuerIdentifier().getIdentifier().toString() + "\n");
sb.append(pp.indent(mIndentSize + 12) +
mResource.getString(
PrettyPrintResources.TOKEN_SUBJECT_DOMAIN_POLICY) +
m.getSubjectIdentifier().getIdentifier().toString() + "\n");
}
}
return sb.toString();
}
/**
* String Representation of SubjectDirAttributesExtension
*/
private String getSubjectDirAttributesExtension() {
StringBuffer sb = new StringBuffer();
try {
sb.append(pp.indent(mIndentSize) + mResource.getString(
PrettyPrintResources.TOKEN_IDENTIFIER));
sb.append(mResource.getString(PrettyPrintResources.TOKEN_SUBJECT_DIR_ATTR) +
"- " + mExt.getExtensionId().toString() + "\n");
sb.append(pp.indent(mIndentSize + 4) +
mResource.getString(PrettyPrintResources.TOKEN_CRITICAL));
if (mExt.isCritical()) {
sb.append(mResource.getString(PrettyPrintResources.TOKEN_YES) + "\n");
} else {
sb.append(mResource.getString(PrettyPrintResources.TOKEN_NO) + "\n");
}
SubjectDirAttributesExtension ext =
(SubjectDirAttributesExtension) mExt;
sb.append(pp.indent(mIndentSize + 4) +
mResource.getString(PrettyPrintResources.TOKEN_ATTRIBUTES));
Enumeration attrs = ext.getAttributesList();
if (attrs == null || !attrs.hasMoreElements()) {
sb.append(
mResource.getString(PrettyPrintResources.TOKEN_NONE) + "\n");
} else {
sb.append("\n");
for (int j = 0; attrs.hasMoreElements(); j++) {
Attribute attr = attrs.nextElement();
sb.append(pp.indent(mIndentSize + 8) +
mResource.getString(
PrettyPrintResources.TOKEN_ATTRIBUTE) + j + ":" + "\n");
sb.append(pp.indent(mIndentSize + 12) +
mResource.getString(
PrettyPrintResources.TOKEN_IDENTIFIER) +
attr.getOid().toString() + "\n");
sb.append(pp.indent(mIndentSize + 12) +
mResource.getString(
PrettyPrintResources.TOKEN_VALUES));
Enumeration values = attr.getValues();
if (values == null || !values.hasMoreElements()) {
sb.append(mResource.getString(
PrettyPrintResources.TOKEN_NONE) + "\n");
} else {
for (int k = 0; values.hasMoreElements(); k++) {
String v = values.nextElement();
if (k != 0)
sb.append(",");
sb.append(v);
}
}
sb.append("\n");
}
}
return sb.toString();
} catch (Throwable e) {
return "";
}
}
private String getCertificatePoliciesExtension() {
StringBuffer sb = new StringBuffer();
try {
sb.append(pp.indent(mIndentSize) + mResource.getString(
PrettyPrintResources.TOKEN_IDENTIFIER));
sb.append(mResource.getString(PrettyPrintResources.TOKEN_CERT_POLICIES) +
"- " + mExt.getExtensionId().toString() + "\n");
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(
PrettyPrintResources.TOKEN_CRITICAL));
if (mExt.isCritical()) {
sb.append(mResource.getString(
PrettyPrintResources.TOKEN_YES) + "\n");
} else {
sb.append(mResource.getString(
PrettyPrintResources.TOKEN_NO) + "\n");
}
sb.append(pp.indent(mIndentSize + 4) + mResource.getString(
PrettyPrintResources.TOKEN_CERT_POLICIES) + "\n");
CertificatePoliciesExtension cp = (CertificatePoliciesExtension) mExt;
@SuppressWarnings("unchecked")
Vector cpv = (Vector) cp.get("infos");
Enumeration e = cpv.elements();
if (e != null) {
while (e.hasMoreElements()) {
CertificatePolicyInfo cpi = e.nextElement();
sb.append(pp.indent(mIndentSize + 8)
+ "Policy Identifier: " + cpi.getPolicyIdentifier().getIdentifier().toString() + "\n");
PolicyQualifiers cpq = cpi.getPolicyQualifiers();
if (cpq != null) {
for (int i = 0; i < cpq.size(); i++) {
PolicyQualifierInfo pq = cpq.getInfoAt(i);
Qualifier q = pq.getQualifier();
if (q instanceof CPSuri) {
sb.append(pp.indent(mIndentSize + 12)
+ "Policy Qualifier Identifier: CPS Pointer Qualifier - "
+ pq.getId() + "\n");
sb.append(pp.indent(mIndentSize + 12)
+ "Policy Qualifier Data: " + ((CPSuri) q).getURI() + "\n");
} else if (q instanceof UserNotice) {
sb.append(pp.indent(mIndentSize + 12)
+ "Policy Qualifier Identifier: CPS User Notice Qualifier - "
+ pq.getId() + "\n");
NoticeReference nref = ((UserNotice) q).getNoticeReference();
DisplayText dt = ((UserNotice) q).getDisplayText();
sb.append(pp.indent(mIndentSize + 12) + "Policy Qualifier Data: \n");
if (nref != null) {
sb.append(pp.indent(mIndentSize + 16)
+ "Organization: " + nref.getOrganization().toString() + "\n");
sb.append(pp.indent(mIndentSize + 16) + "Notice Numbers: ");
int[] nums = nref.getNumbers();
for (int k = 0; k < nums.length; k++) {
if (k != 0) {
sb.append(",");
sb.append(nums[k]);
} else {
sb.append(nums[k]);
}
}
sb.append("\n");
}
if (dt != null) {
sb.append(pp.indent(mIndentSize + 16) + "Explicit Text: " + dt.toString() + "\n");
}
}
}
}
}
}
return sb.toString();
} catch (IOException e) {
return sb.toString();
}
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/util/IA5Charset.java 0000664 0000000 0000000 00000001073 14565430767 0030126 0 ustar 00root root 0000000 0000000 package org.mozilla.jss.netscape.security.util;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
public class IA5Charset extends Charset {
public IA5Charset() {
super("ASN.1-IA5", null);
}
@Override
public boolean contains(Charset cs) {
return false;
}
@Override
public CharsetDecoder newDecoder() {
return new IA5CharsetDecoder(this);
}
@Override
public CharsetEncoder newEncoder() {
return new IA5CharsetEncoder(this);
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/util/IA5CharsetDecoder.java 0000664 0000000 0000000 00000003570 14565430767 0031420 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.util;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CoderResult;
import java.nio.charset.CodingErrorAction;
/**
* Converts bytes in ASN.1 IA5String character set to IA5String characters.
*
* @author Lily Hsiao
* @author Slava Galperin
*/
public class IA5CharsetDecoder extends CharsetDecoder {
public IA5CharsetDecoder(Charset cs) {
super(cs, 1, 1);
}
@Override
protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) {
while (true) {
if (in.remaining() < 1)
return CoderResult.UNDERFLOW;
in.mark();
byte b = in.get();
if (CodingErrorAction.REPORT == unmappableCharacterAction() && (b & 0x80) != 0) {
return CoderResult.unmappableForLength(1);
}
if (out.remaining() < 1) {
in.reset();
return CoderResult.OVERFLOW;
}
out.put((char) (b & 0x7f));
}
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/util/IA5CharsetEncoder.java 0000664 0000000 0000000 00000004206 14565430767 0031427 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.util;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
import java.nio.charset.CodingErrorAction;
/**
* Converts characters in ASN.1 IA5String character set to IA5String bytes.
*
* @author Lily Hsiao
* @author Slava Galperin
*/
public class IA5CharsetEncoder extends CharsetEncoder {
public IA5CharsetEncoder(Charset cs) {
super(cs, 1, 1);
}
/*
* Converts an array of Unicode characters into an array of IA5String
* bytes and returns the conversion result.
* @param in input character buffer to convert.
* @param out byte buffer to store output.
* @return encoding result.
*/
@Override
protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) {
while (true) {
if (in.remaining() < 1)
return CoderResult.UNDERFLOW;
in.mark();
char c = in.get();
if (CodingErrorAction.REPORT == unmappableCharacterAction() && (c & 0xFF80) != 0) {
return CoderResult.unmappableForLength(1);
}
if (out.remaining() < 1) {
in.reset();
return CoderResult.OVERFLOW;
}
out.put((byte) (c & 0x7f));
}
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/util/ObjectIdentifier.java 0000664 0000000 0000000 00000036604 14565430767 0031457 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.util;
import java.io.IOException;
import java.io.Serializable;
import java.math.BigInteger;
import java.util.HashMap;
import java.util.Map;
import java.util.StringTokenizer;
/**
* Represent an ISO Object Identifier.
*
*
* Object Identifiers are arbitrary length hierarchical identifiers. The individual components are numbers, and they
* define paths from the root of an ISO-managed identifier space. You will sometimes see a string name used instead of
* (or in addition to) the numerical id. These are synonyms for the numerical IDs, but are not widely used since most
* sites do not know all the requisite strings, while all sites can parse the numeric forms.
*
*
* So for example, JavaSoft has the sole authority to assign the meaning to identifiers below the 1.3.6.1.4.42.2.17 node
* in the hierarchy, and other organizations can easily acquire the ability to assign such unique identifiers.
*
* @version 1.23
*
* @author David Brownell
* @author Amit Kapoor
* @author Hemma Prafullchandra
*/
public final class ObjectIdentifier implements Serializable {
/** use serialVersionUID from JDK 1.1. for interoperability */
private static final long serialVersionUID = 8697030238860181294L;
/**
* Constructs an object identifier from a string. This string
* should be of the form 1.23.34.45.56 etc.
*/
public ObjectIdentifier(String oid) {
if (oid == null)
return;
int ch = '.';
int start = 0;
int end = 0;
// Calculate length of oid
componentLen = 0;
while ((end = oid.indexOf(ch, start)) != -1) {
start = end + 1;
componentLen += 1;
}
componentLen += 1;
components = new BigInteger[componentLen];
start = 0;
int i = 0;
String comp = null;
while ((end = oid.indexOf(ch, start)) != -1) {
comp = oid.substring(start, end);
components[i++] = new BigInteger(comp);
start = end + 1;
}
comp = oid.substring(start);
components[i] = new BigInteger(comp);
}
/**
* Constructs an object ID from an array of integers. This
* is used to construct constant object IDs.
*/
public ObjectIdentifier(int[] values) {
try {
componentLen = values.length;
BigInteger[] tmp = new BigInteger[componentLen];
for (int i = 0; i < componentLen; i++) {
tmp[i] = BigInteger.valueOf(values[i]);
}
components = tmp.clone();
} catch (Exception t) {
System.out.println("X509.ObjectIdentifier(), no cloning!");
}
}
public ObjectIdentifier(BigInteger[] values) {
try {
componentLen = values.length;
componentLen = values.length;
BigInteger[] tmp = new BigInteger[componentLen];
for (int i = 0; i < componentLen; i++) {
tmp[i] = new BigInteger(values[i].toString());
}
components = tmp.clone();
} catch(Exception t) {
System.out.println("X509.ObjectIdentifier(), no cloning!");
}
}
/**
* Constructs an object ID from an array of longs This
* is used to construct constant object IDs.
*/
public ObjectIdentifier(long[] values) {
try {
componentLen = values.length;
BigInteger[] tmp = new BigInteger[componentLen];
for (int i = 0; i < componentLen; i++) {
tmp[i] = BigInteger.valueOf(values[i]);
}
components = tmp.clone();
} catch (Exception t) {
System.out.println("X509.ObjectIdentifier(), no cloning!");
}
}
/**
* Constructs an object ID from an ASN.1 encoded input stream.
* The encoding of the ID in the stream uses "DER", a BER/1 subset.
* In this case, that means a triple { typeId, length, data }.
*
*
* NOTE: When an exception is thrown, the input stream has not been returned to its "initial"
* state.
*
* @param in DER-encoded data holding an object ID
* @exception IOException indicates a decoding error
*/
public ObjectIdentifier(DerInputStream in)
throws IOException {
byte typeId;
int bufferEnd;
/*
* Object IDs are a "universal" type, and their tag needs only
* one byte of encoding. Verify that the tag of this datum
* is that of an object ID.
*
* Then get and check the length of the ID's encoding. We set
* up so that we can use in.available() to check for the end of
* this value in the data stream.
*/
typeId = (byte) in.getByte();
if (typeId != DerValue.tag_ObjectId)
throw new IOException(
"X509.ObjectIdentifier() -- data isn't an object ID"
+ " (tag = " + typeId + ")");
bufferEnd = in.available() - in.getLength() - 1;
if (bufferEnd < 0)
throw new IOException(
"X509.ObjectIdentifier() -- not enough data");
initFromEncoding(in, bufferEnd);
}
/*
* Build the OID from the rest of a DER input buffer; the tag
* and length have been removed/verified
*/
ObjectIdentifier(DerInputBuffer buf) throws IOException {
initFromEncoding(new DerInputStream(buf), 0);
}
/*
* Helper function -- get the OID from a stream, after tag and
* length are verified.
*/
private void initFromEncoding(DerInputStream in, int bufferEnd)
throws IOException {
/*
* Now get the components ("sub IDs") one at a time. We fill a
* temporary buffer, resizing it as needed.
*/
BigInteger component;
boolean firstSubid = true;
for (components = new BigInteger[ALLOCATION_QUANTUM], componentLen = 0; in.available() > bufferEnd;) {
component = getComponentBigInt(in);
if (firstSubid) {
long x;
long y;
/*
* The ISO root has three children (0, 1, 2) and those nodes
* aren't allowed to assign IDs larger than 39. These rules
* are memorialized by some special casing in the BER encoding
* of object IDs ... or maybe it's vice versa.
*
* NOTE: the allocation quantum is large enough that we know
* we don't have to reallocate here!
*/
if (component.intValue() < 40)
x = 0;
else if (component.intValue() < 80)
x = 1;
else
x = 2;
y = component.intValue() - (x * 40);
components[0] = BigInteger.valueOf(x);
components[1] = BigInteger.valueOf(y);
componentLen = 2;
firstSubid = false;
} else {
/*
* Other components are encoded less exotically. The only
* potential trouble is the need to grow the array.
*/
if (componentLen >= components.length) {
BigInteger[] tmpComponents;
tmpComponents = new BigInteger[components.length
+ ALLOCATION_QUANTUM];
System.arraycopy(components, 0, tmpComponents, 0,
components.length);
components = tmpComponents;
}
components[componentLen++] = component;
}
}
/*
* Final sanity check -- if we didn't use exactly the number of bytes
* specified, something's quite wrong.
*/
if (in.available() != bufferEnd) {
throw new IOException(
"X509.ObjectIdentifier() -- malformed input data");
}
}
/*
* n.b. the only public interface is DerOutputStream.putOID()
*/
public void encode(DerOutputStream out) throws IOException {
DerOutputStream bytes = new DerOutputStream();
int i;
/* We can use the int here because we know we are dealing
with small numbers for the first byte
*/
bytes.write((components[0].intValue() * 40) + components[1].intValue());
for (i = 2; i < componentLen; i++)
putComponentBigInt(bytes, components[i]);
/*
* Now that we've constructed the component, encode
* it in the stream we were given.
*/
out.write(DerValue.tag_ObjectId, bytes);
}
/*
* Tricky OID component parsing technique ... note that one bit
* per octet is lost, this returns at most 28 bits of component.
* Also, notice this parses in big-endian format.
*/
private static BigInteger getComponentBigInt(DerInputStream in)
throws IOException {
BigInteger retval = BigInteger.valueOf(0);
int tmp;
while (true) {
retval = retval.shiftLeft(7);
tmp = in.getByte();
retval = retval.or(BigInteger.valueOf(tmp & 0x07f));
if ((tmp & 0x080) == 0)
return retval;
}
}
/*
* Reverse of the above routine. Notice it needs to emit in
* big-endian form, so it buffers the output until it's ready.
* (Minimum length encoding is a DER requirement.)
*/
private static void putComponentBigInt(DerOutputStream out, BigInteger val) {
int i;
int blockSize = 100;
byte[] buf = new byte[blockSize];
BigInteger bigInt7f = BigInteger.valueOf(0x7f);
BigInteger cur = new BigInteger(val.toString());
for (i = 0;; i++) {
buf[i] = (cur.and(bigInt7f).byteValue());
cur = cur.shiftRight(7);
if (cur.compareTo(BigInteger.ZERO) == 0 )
break;
}
for (; i > 0; --i)
out.write(buf[i] | 0x080);
out.write(buf[0]);
}
// XXX this API should probably facilitate the JDK sort utility
/**
* Compares this identifier with another, for sorting purposes.
* An identifier does not precede itself.
*
* @param other identifer that may precede this one.
* @return true iff other precedes this one
* in a particular sorting order.
*/
public boolean precedes(ObjectIdentifier other) {
int i;
// shorter IDs go first
if (other == this || componentLen < other.componentLen)
return false;
if (other.componentLen < componentLen)
return true;
// for each component, the lesser component goes first
for (i = 0; i < componentLen; i++) {
if (other.components[i].compareTo(components[i]) > 0)
return true;
}
// identical IDs don't precede each other
return false;
}
@Override
public boolean equals(Object other) {
return other instanceof ObjectIdentifier oi && equals(oi);
}
/**
* Compares this identifier with another, for equality.
*
* @return true iff the names are identical.
*/
public boolean equals(ObjectIdentifier other) {
int i;
if (other == this)
return true;
if (componentLen != other.componentLen)
return false;
for (i = 0; i < componentLen; i++) {
if (components[i].compareTo(other.components[i]) != 0 )
return false;
}
return true;
}
@Override
public int hashCode() {
int h = 0;
int oflow = 0;
for (int i = 0; i < componentLen; i++) {
oflow = (h & 0xff800000) >> 23;
h <<= 9;
h += components[i].intValue();
h ^= oflow;
}
return h;
}
/**
* Returns a string form of the object ID. The format is the
* conventional "dot" notation for such IDs, without any
* user-friendly descriptive strings, since those strings
* will not be understood everywhere.
*/
@Override
public String toString() {
StringBuilder retval = new StringBuilder();
int i;
for (i = 0; i < componentLen; i++) {
if (i != 0)
retval.append(".");
retval.append(components[i]);
}
return retval.toString();
}
/*
* To simplify, we assume no individual component of an object ID is
* larger than 64 bits. Then we represent the path from the root as
* an array that's (usually) only filled at the beginning.
*/
private BigInteger[] components; // path from root
private int componentLen; // how much is used.
private static final int ALLOCATION_QUANTUM = 5; // >= 2
/**
* Netscape Enhancement:
* This function implements a object identifier factory. It
* should help reduces in-memory Object Identifier object.
* This function also provide additional checking on the OID.
* A valid OID should start with 0, 1, or 2.
*
* Notes:
* This function never returns null. IOException is raised
* in error conditions.
*/
private static Map mOIDs = new HashMap<>();
public static ObjectIdentifier getObjectIdentifier(String oid)
throws IOException {
int value;
if (oid == null)
throw new IOException("empty object identifier");
oid = oid.trim();
ObjectIdentifier thisOID = mOIDs.get(oid);
if (thisOID != null)
return thisOID;
StringTokenizer token = new StringTokenizer(oid, ".");
value = Integer.valueOf(token.nextToken());
/* First token should be 0, 1, 2 */
if (value < 0 || value > 2)
throw new IOException("invalid oid " + oid);
value = Integer.valueOf(token.nextToken());
/* Second token should be 0 <= && >= 39 */
if (value < 0 || value > 39)
throw new IOException("invalid oid " + oid);
thisOID = new ObjectIdentifier(oid);
if (thisOID.toString().equals(oid)) {
mOIDs.put(oid, thisOID);
return thisOID;
}
throw new IOException("invalid oid " + oid);
}
public static ObjectIdentifier getObjectIdentifier(int[] values)
throws IOException {
StringBuilder retval = new StringBuilder();
int i;
for (i = 0; i < values.length; i++) {
if (i != 0)
retval.append(".");
retval.append(values[i]);
}
return getObjectIdentifier(retval.toString());
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/util/PrettyPrintFormat.java 0000664 0000000 0000000 00000012231 14565430767 0031711 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.util;
/**
* This class will display the certificate content in predefined
* format.
*
* @author Andrew Wnuk
* @version $Revision$, $Date$
*/
public class PrettyPrintFormat {
/*==========================================================
* variables
*==========================================================*/
private String mSeparator = "";
private int mIndentSize = 0;
private int mLineLen = 0;
/*==========================================================
* constants
*
*==========================================================*/
private final static String spaces =
" " +
" " +
" " +
" " +
" ";
/*==========================================================
* constructors
*==========================================================*/
public PrettyPrintFormat(String separator) {
mSeparator = separator;
}
public PrettyPrintFormat(String separator, int lineLen) {
mSeparator = separator;
mLineLen = lineLen;
}
public PrettyPrintFormat(String separator, int lineLen, int indentSize) {
mSeparator = separator;
mLineLen = lineLen;
mIndentSize = indentSize;
}
/*==========================================================
* Private methods
*==========================================================*/
/*==========================================================
* public methods
*==========================================================*/
/**
* Provide white space indention
* stevep - speed improvements. Factor of 10 improvement
*
* @param size number of white space to be returned
* @return white spaces
*/
public String indent(int size) {
return spaces.substring(0, size);
}
private static final char[] hexdigits = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'A', 'B', 'C', 'D', 'E', 'F'
};
/**
* Convert Byte Array to Hex String Format
* stevep - speedup by factor of 8
*
* @param in byte array of data to hexify
* @param indentSize number of spaces to prepend before each line
* @param lineLen number of bytes to output on each line (0
* means: put everything on one line
* @param separator the first character of this string will be used as
* the separator between bytes.
* @return string representation
*/
public String toHexString(byte[] in, int indentSize,
int lineLen, String separator) {
if (in == null) {
return "";
}
StringBuffer sb = new StringBuffer();
int hexCount = 0;
char c[];
int j = 0;
if (lineLen == 0) {
c = new char[in.length * 3 + 1];
} else {
c = new char[lineLen * 3 + 1];
}
char sep = separator.charAt(0);
sb.append(indent(indentSize));
for (int i = 0; i < in.length; i++) {
if (lineLen > 0 && hexCount == lineLen) {
c[j++] = '\n';
sb.append(c, 0, j);
sb.append(indent(indentSize));
hexCount = 0;
j = 0;
}
byte x = in[i];
// output hex digits to buffer
c[j++] = hexdigits[(char) ((x >> 4) & 0xf)];
c[j++] = hexdigits[(char) (x & 0xf)];
// if not last char, output separator
if (i != in.length - 1) {
c[j++] = sep;
}
hexCount++;
}
if (j > 0) {
c[j++] = '\n';
sb.append(c, 0, j);
}
// sb.append("\n");
return sb.toString();
}
public String toHexString(byte[] in, int indentSize, int lineLen) {
return toHexString(in, indentSize, lineLen, mSeparator);
}
public String toHexString(byte[] in, int indentSize) {
return toHexString(in, indentSize, mLineLen);
}
public String toHexString(byte[] in) {
return toHexString(in, mIndentSize);
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/util/PrettyPrintResources.java 0000664 0000000 0000000 00000036536 14565430767 0032451 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.util;
import java.util.ListResourceBundle;
import org.mozilla.jss.netscape.security.extensions.NSCertTypeExtension;
import org.mozilla.jss.netscape.security.x509.KeyUsageExtension;
/**
* Resource Boundle for the Pretty Print
*
* @author Jack Pan-Chen
* @version $Revision$, $Date$
*/
public class PrettyPrintResources extends ListResourceBundle {
/**
* Returns content
*/
@Override
public Object[][] getContents() {
return contents;
}
/**
* Constants. The suffix represents the number of
* possible parameters.
*/
//certificate pretty print
public final static String TOKEN_CERTIFICATE = "tokenCertificate";
public final static String TOKEN_DATA = "tokenData";
public final static String TOKEN_VERSION = "tokenVersion";
public final static String TOKEN_SERIAL = "tokenSerial";
public final static String TOKEN_SIGALG = "tokenSignatureAlgorithm";
public final static String TOKEN_ISSUER = "tokenIssuer";
public final static String TOKEN_VALIDITY = "tokenValidity";
public final static String TOKEN_NOT_BEFORE = "tokenNotBefore";
public final static String TOKEN_NOT_AFTER = "tokenNotAfter";
public final static String TOKEN_SUBJECT = "tokenSubject";
public final static String TOKEN_SPKI = "tokenSPKI";
public final static String TOKEN_ALGORITHM = "tokenAlgorithm";
public final static String TOKEN_PUBLIC_KEY = "tokenPublicKey";
public final static String TOKEN_PUBLIC_KEY_MODULUS = "tokenPublicKeyModulus";
public final static String TOKEN_PUBLIC_KEY_EXPONENT = "tokenPublicKeyExponent";
public final static String TOKEN_EXTENSIONS = "tokenExtensions";
public final static String TOKEN_SIGNATURE = "tokenSignature";
//extension pretty print
public final static String TOKEN_YES = "tokenYes";
public final static String TOKEN_NO = "tokenNo";
public final static String TOKEN_IDENTIFIER = "tokenIdentifier";
public final static String TOKEN_CRITICAL = "tokenCritical";
public final static String TOKEN_VALUE = "tokenValue";
//specific extension token
public final static String TOKEN_KEY_TYPE = "tokenKeyType";
public final static String TOKEN_CERT_TYPE = "tokenCertType";
public final static String TOKEN_SKI = "tokenSKI";
public final static String TOKEN_AKI = "tokenAKI";
public final static String TOKEN_ACCESS_DESC = "tokenAccessDesc";
public final static String TOKEN_OCSP_NOCHECK = "tokenOcspNoCheck";
public final static String TOKEN_EXTENDED_KEY_USAGE = "tokenExtendedKeyUsage";
public final static String TOKEN_PRIVATE_KEY_USAGE = "tokenPrivateKeyUsage";
public final static String TOKEN_PRESENCE_SERVER = "tokenPresenceServer";
public final static String TOKEN_AIA = "tokenAIA";
public final static String TOKEN_CERT_POLICIES = "tokenCertPolicies";
public final static String TOKEN_SIA = "tokenSIA";
public final static String TOKEN_KEY_USAGE = "tokenKeyUsage";
public final static String TOKEN_CERT_USAGE = "tokenCertUsage";
public final static String TOKEN_KEY_ID = "tokenKeyId";
public final static String TOKEN_AUTH_NAME = "tokenAuthName";
public final static String TOKEN_CRL = "tokenCRL";
public final static String TOKEN_THIS_UPDATE = "tokenThisUpdate";
public final static String TOKEN_NEXT_UPDATE = "tokenNextUpdate";
public final static String TOKEN_REVOKED_CERTIFICATES = "revokedCerts";
public final static String TOKEN_REVOCATION_DATE = "revocationDate";
public final static String TOKEN_REVOCATION_REASON = "revocationReason";
public final static String TOKEN_REASON = "reason";
public final static String TOKEN_BASIC_CONSTRAINTS = "basicConstraints";
public final static String TOKEN_NAME_CONSTRAINTS = "tokenNameConstraints";
public final static String TOKEN_NSC_COMMENT = "tokenNSCComment";
public final static String TOKEN_IS_CA = "isCA";
public final static String TOKEN_PATH_LEN = "pathLen";
public final static String TOKEN_PATH_LEN_UNLIMITED = "pathLenUnlimited";
public final static String TOKEN_PATH_LEN_UNDEFINED = "pathLenUndefined";
public final static String TOKEN_PATH_LEN_INVALID = "pathLenInvalid";
public final static String TOKEN_CRL_NUMBER = "CRLNumber";
public final static String TOKEN_NUMBER = "Number";
public final static String TOKEN_DELTA_CRL_INDICATOR = "DeltaCRLIndicator";
public final static String TOKEN_BASE_CRL_NUMBER = "BaseCRLNumber";
public final static String TOKEN_CERT_SCOPE_OF_USE = "CertificateScopeOfUse";
public final static String TOKEN_SCOPE_OF_USE = "ScopeOfUse";
public final static String TOKEN_PORT = "Port";
public final static String TOKEN_ISSUER_ALT_NAME = "IssuerAlternativeName";
public final static String TOKEN_ISSUER_NAMES = "IssuerNames";
public final static String TOKEN_SUBJECT_ALT_NAME = "SubjectAlternativeName";
public final static String TOKEN_SUBJECT_NAME = "SubjectName";
public final static String TOKEN_DECODING_ERROR = "decodingError";
public final static String TOKEN_FRESHEST_CRL_EXT = "FreshestCRL";
public final static String TOKEN_INHIBIT_ANY_POLICY_EXT = "InhibitAnyPolicy";
public final static String TOKEN_SKIP_CERTS = "SkipCerts";
public final static String TOKEN_CRL_DP_EXT = "CRLDistributionPoints";
public final static String TOKEN_CRLDP_NUMPOINTS = "CRLDP_NUMPOINTS";
public final static String TOKEN_CRLDP_POINTN = "CRLDP_POINTN";
public final static String TOKEN_CRLDP_DISTPOINT = "CRLDP_DISTPOINT";
public final static String TOKEN_CRLDP_REASONS = "CRLDP_REASONS";
public final static String TOKEN_CRLDP_CRLISSUER = "CRLDP_CRLISSUER";
public final static String TOKEN_ISSUING_DIST_POINT = "IssuingDistributionPoint";
public final static String TOKEN_DIST_POINT_NAME = "DistributionPointName";
public final static String TOKEN_FULL_NAME = "FullName";
public final static String TOKEN_RELATIVE_NAME = "NameRelativeToCRLIssuer";
public final static String TOKEN_ONLY_USER_CERTS = "OnlyContainsUserCerts";
public final static String TOKEN_ONLY_CA_CERTS = "OnlyContainsCACerts";
public final static String TOKEN_ONLY_SOME_REASONS = "OnlySomeReasons";
public final static String TOKEN_INDIRECT_CRL = "IndirectCRL";
public final static String TOKEN_INVALIDITY_DATE = "invalidityDate";
public final static String TOKEN_DATE_OF_INVALIDITY = "dateOfInvalidity";
public final static String TOKEN_CERTIFICATE_ISSUER = "CertificateIssuer";
public final static String TOKEN_HOLD_INSTRUCTION = "HoldInstruction";
public final static String TOKEN_HOLD_INSTRUCTION_CODE = "HoldInstructionCode";
public final static String TOKEN_POLICY_CONSTRAINTS = "PolicyConstraints";
public final static String TOKEN_POLICY_MAPPINGS = "PolicyMappings";
public final static String TOKEN_SUBJECT_DIR_ATTR = "SubjectDirectoryAttributes";
// policy constriants extension fields
public final static String TOKEN_INHIBIT_POLICY_MAPPING = "inhibitPolicyMapping";
public final static String TOKEN_REQUIRE_EXPLICIT_POLICY = "requireExplicitPolicy";
// policy mappings extension fields
public final static String TOKEN_MAPPINGS = "mappings";
public final static String TOKEN_MAP = "map";
public final static String TOKEN_ISSUER_DOMAIN_POLICY = "issuerDomainPolicy";
public final static String TOKEN_SUBJECT_DOMAIN_POLICY = "subjectDomainPolicy";
// subject directory attribute fields
public final static String TOKEN_ATTRIBUTES = "Attributes";
public final static String TOKEN_ATTRIBUTE = "Attribute";
public final static String TOKEN_VALUES = "Values";
// field values
public final static String TOKEN_NOT_SET = "notSet";
public final static String TOKEN_NONE = "none";
public final static String TOKEN_CACHE_NOT_AVAILABLE = "cacheNotAvailable";
public final static String TOKEN_CACHE_IS_EMPTY = "cacheIsEmpty";
//Tokens should have blank_space as trailer
static final Object[][] contents = {
{ TOKEN_CERTIFICATE, "Certificate: " },
{ TOKEN_DATA, "Data: " },
{ TOKEN_VERSION, "Version: " },
{ TOKEN_SERIAL, "Serial Number: " },
{ TOKEN_SIGALG, "Signature Algorithm: " },
{ TOKEN_ISSUER, "Issuer: " },
{ TOKEN_VALIDITY, "Validity: " },
{ TOKEN_NOT_BEFORE, "Not Before: " },
{ TOKEN_NOT_AFTER, "Not After: " },
{ TOKEN_SUBJECT, "Subject: " },
{ TOKEN_SPKI, "Subject Public Key Info: " },
{ TOKEN_ALGORITHM, "Algorithm: " },
{ TOKEN_PUBLIC_KEY, "Public Key: " },
{ TOKEN_PUBLIC_KEY_MODULUS, "Public Key Modulus: " },
{ TOKEN_PUBLIC_KEY_EXPONENT, "Exponent: " },
{ TOKEN_EXTENSIONS, "Extensions: " },
{ TOKEN_SIGNATURE, "Signature: " },
{ TOKEN_YES, "yes " },
{ TOKEN_NO, "no " },
{ TOKEN_IDENTIFIER, "Identifier: " },
{ TOKEN_CRITICAL, "Critical: " },
{ TOKEN_VALUE, "Value: " },
{ TOKEN_KEY_TYPE, "Key Type " },
{ TOKEN_CERT_TYPE, "Netscape Certificate Type " },
{ TOKEN_SKI, "Subject Key Identifier " },
{ TOKEN_AKI, "Authority Key Identifier " },
{ TOKEN_ACCESS_DESC, "Access Description: " },
{ TOKEN_OCSP_NOCHECK, "OCSP NoCheck: " },
{ TOKEN_EXTENDED_KEY_USAGE, "Extended Key Usage: " },
{ TOKEN_PRIVATE_KEY_USAGE, "Private Key Usage: " },
{ TOKEN_PRESENCE_SERVER, "Presence Server: " },
{ TOKEN_AIA, "Authority Info Access: " },
{ TOKEN_CERT_POLICIES, "Certificate Policies: " },
{ TOKEN_SIA, "Subject Info Access: " },
{ TOKEN_KEY_USAGE, "Key Usage: " },
{ KeyUsageExtension.DIGITAL_SIGNATURE, "Digital Signature " },
{ KeyUsageExtension.NON_REPUDIATION, "Non Repudiation " },
{ KeyUsageExtension.KEY_ENCIPHERMENT, "Key Encipherment " },
{ KeyUsageExtension.DATA_ENCIPHERMENT, "Data Encipherment " },
{ KeyUsageExtension.KEY_AGREEMENT, "Key Agreement " },
{ KeyUsageExtension.KEY_CERTSIGN, "Key CertSign " },
{ KeyUsageExtension.CRL_SIGN, "Crl Sign " },
{ KeyUsageExtension.ENCIPHER_ONLY, "Encipher Only " },
{ KeyUsageExtension.DECIPHER_ONLY, "Decipher Only " },
{ TOKEN_CERT_USAGE, "Certificate Usage: " },
{ NSCertTypeExtension.SSL_CLIENT, "SSL Client " },
{ NSCertTypeExtension.SSL_SERVER, "SSL Server " },
{ NSCertTypeExtension.EMAIL, "Secure Email " },
{ NSCertTypeExtension.OBJECT_SIGNING, "Object Signing " },
{ NSCertTypeExtension.SSL_CA, "SSL CA " },
{ NSCertTypeExtension.EMAIL_CA, "Secure Email CA " },
{ NSCertTypeExtension.OBJECT_SIGNING_CA, "ObjectSigning CA " },
{ TOKEN_KEY_ID, "Key Identifier: " },
{ TOKEN_AUTH_NAME, "Authority Name: " },
{ TOKEN_CRL, "Certificate Revocation List: " },
{ TOKEN_THIS_UPDATE, "This Update: " },
{ TOKEN_NEXT_UPDATE, "Next Update: " },
{ TOKEN_REVOKED_CERTIFICATES, "Revoked Certificates: " },
{ TOKEN_REVOCATION_DATE, "Revocation Date: " },
{ TOKEN_REVOCATION_REASON, "Revocation Reason " },
{ TOKEN_REASON, "Reason: " },
{ TOKEN_BASIC_CONSTRAINTS, "Basic Constraints " },
{ TOKEN_NAME_CONSTRAINTS, "Name Constraints " },
{ TOKEN_NSC_COMMENT, "Netscape Comment " },
{ TOKEN_IS_CA, "Is CA: " },
{ TOKEN_PATH_LEN, "Path Length Constraint: " },
{ TOKEN_PATH_LEN_UNLIMITED, "UNLIMITED" },
{ TOKEN_PATH_LEN_UNDEFINED, "UNDEFINED" },
{ TOKEN_PATH_LEN_INVALID, "INVALID" },
{ TOKEN_CRL_NUMBER, "CRL Number " },
{ TOKEN_NUMBER, "Number: " },
{ TOKEN_DELTA_CRL_INDICATOR, "Delta CRL Indicator " },
{ TOKEN_BASE_CRL_NUMBER, "Base CRL Number: " },
{ TOKEN_CERT_SCOPE_OF_USE, "Certificate Scope of Use " },
{ TOKEN_SCOPE_OF_USE, "Scope of Use: " },
{ TOKEN_PORT, "Port: " },
{ TOKEN_ISSUER_ALT_NAME, "Issuer Alternative Name " },
{ TOKEN_ISSUER_NAMES, "Issuer Names: " },
{ TOKEN_SUBJECT_ALT_NAME, "Subject Alternative Name " },
{ TOKEN_DECODING_ERROR, "Decoding Error" },
{ TOKEN_FRESHEST_CRL_EXT, "Freshest CRL " },
{ TOKEN_INHIBIT_ANY_POLICY_EXT, "Inhibit Any-Policy " },
{ TOKEN_SKIP_CERTS, "Skip Certs: " },
{ TOKEN_CRL_DP_EXT, "CRL Distribution Points " },
{ TOKEN_CRLDP_NUMPOINTS, "Number of Points: " },
{ TOKEN_CRLDP_POINTN, "Point " },
{ TOKEN_CRLDP_DISTPOINT, "Distribution Point: " },
{ TOKEN_CRLDP_REASONS, "Reason Flags: " },
{ TOKEN_CRLDP_CRLISSUER, "CRL Issuer: " },
{ TOKEN_ISSUING_DIST_POINT, "Issuing Distribution Point " },
{ TOKEN_DIST_POINT_NAME, "Distribution Point: " },
{ TOKEN_FULL_NAME, "Full Name: " },
{ TOKEN_RELATIVE_NAME, "Name Relative To CRL Issuer: " },
{ TOKEN_ONLY_USER_CERTS, "Only Contains User Certificates: " },
{ TOKEN_ONLY_CA_CERTS, "Only Contains CA Certificates: " },
{ TOKEN_ONLY_SOME_REASONS, "Only Some Reasons: " },
{ TOKEN_INDIRECT_CRL, "Indirect CRL: " },
{ TOKEN_INVALIDITY_DATE, "Invalidity Date " },
{ TOKEN_DATE_OF_INVALIDITY, "Invalidity Date: " },
{ TOKEN_CERTIFICATE_ISSUER, "Certificate Issuer " },
{ TOKEN_HOLD_INSTRUCTION, "Hold Instruction Code " },
{ TOKEN_HOLD_INSTRUCTION_CODE, "Hold Instruction Code: " },
{ TOKEN_POLICY_CONSTRAINTS, "Policy Constraints " },
{ TOKEN_INHIBIT_POLICY_MAPPING, "Inhibit Policy Mapping: " },
{ TOKEN_REQUIRE_EXPLICIT_POLICY, "Require Explicit Policy: " },
{ TOKEN_POLICY_MAPPINGS, "Policy Mappings " },
{ TOKEN_MAPPINGS, "Mappings: " },
{ TOKEN_MAP, "Map " },
{ TOKEN_ISSUER_DOMAIN_POLICY, "Issuer Domain Policy: " },
{ TOKEN_SUBJECT_DOMAIN_POLICY, "Subject Domain Policy: " },
{ TOKEN_SUBJECT_DIR_ATTR, "Subject Directory Attributes " },
{ TOKEN_ATTRIBUTES, "Attributes:" },
{ TOKEN_ATTRIBUTE, "Attribute " },
{ TOKEN_VALUES, "Values: " },
{ TOKEN_NOT_SET, "not set" },
{ TOKEN_NONE, "none" },
{ TOKEN_CACHE_NOT_AVAILABLE, "CRL cache is not available. " },
{ TOKEN_CACHE_IS_EMPTY, "CRL cache is empty. " },
};
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/util/PrintableCharset.java 0000664 0000000 0000000 00000002140 14565430767 0031464 0 ustar 00root root 0000000 0000000 package org.mozilla.jss.netscape.security.util;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
public class PrintableCharset extends Charset {
public PrintableCharset() {
super("ASN.1-Printable", null);
}
public static boolean isPrintableChar(char c) {
return (c >= 'A' && c <= 'Z')
|| (c >= 'a' && c <= 'z')
|| (c >= '0' && c <= '9')
|| c == ' '
|| c == '\''
|| c == '('
|| c == ')'
|| c == '+'
|| c == ','
|| c == '-'
|| c == '.'
|| c == '/'
|| c == ':'
|| c == '='
|| c == '?';
}
@Override
public boolean contains(Charset cs) {
return false;
}
@Override
public CharsetDecoder newDecoder() {
return new PrintableCharsetDecoder(this);
}
@Override
public CharsetEncoder newEncoder() {
return new PrintableCharsetEncoder(this);
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/util/PrintableCharsetDecoder.java 0000664 0000000 0000000 00000004071 14565430767 0032757 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.util;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CoderResult;
import java.nio.charset.CodingErrorAction;
/**
* Converts bytes in ASN.1 PrintableString character set to PrintableString
* characters.
*
* @author Lily Hsiao
* @author Slava Galperin
*/
public class PrintableCharsetDecoder extends CharsetDecoder {
public PrintableCharsetDecoder(Charset cs) {
super(cs, 1, 1);
}
@Override
protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) {
while (true) {
if (in.remaining() < 1)
return CoderResult.UNDERFLOW;
in.mark();
byte b = in.get();
char c = (char) (b & 0x7f);
if (CodingErrorAction.REPORT == unmappableCharacterAction() &&
!PrintableCharset.isPrintableChar(c)) {
/*
"bug" fix for 359010
return CoderResult.unmappableForLength(1);
*/
continue;
}
if (out.remaining() < 1) {
in.reset();
return CoderResult.OVERFLOW;
}
out.put(c);
}
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/util/PrintableCharsetEncoder.java 0000664 0000000 0000000 00000004316 14565430767 0032773 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.util;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
import java.nio.charset.CodingErrorAction;
/**
* Converts characters in ASN.1 PrintableString character set to PrintableString
* bytes.
*
* @author Lily Hsiao
* @author Slava Galperin
*/
public class PrintableCharsetEncoder extends CharsetEncoder {
public PrintableCharsetEncoder(Charset cs) {
super(cs, 1, 1);
}
/*
* Converts an array of Unicode characters into an array of PrintableString
* bytes and returns the conversion result.
* @param in input character buffer to convert.
* @param out byte buffer to store output.
* @return encoding result.
*/
@Override
protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) {
while (true) {
if (in.remaining() < 1)
return CoderResult.UNDERFLOW;
in.mark();
char c = in.get();
if (CodingErrorAction.REPORT == unmappableCharacterAction() &&
!PrintableCharset.isPrintableChar(c)) {
return CoderResult.unmappableForLength(1);
}
if (out.remaining() < 1) {
in.reset();
return CoderResult.OVERFLOW;
}
out.put((byte) (c & 0x7f));
}
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/util/PubKeyPrettyPrint.java 0000664 0000000 0000000 00000011174 14565430767 0031665 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.util;
import java.security.InvalidKeyException;
import java.security.PublicKey;
import java.util.Locale;
import java.util.ResourceBundle;
import org.mozilla.jss.netscape.security.provider.RSAPublicKey;
import org.mozilla.jss.netscape.security.x509.X509Key;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This class will display the certificate content in predefined
* format.
*
* @author Jack Pan-Chen
* @author Andrew Wnuk
* @version $Revision$, $Date$
*/
public class PubKeyPrettyPrint {
public static final Logger logger = LoggerFactory.getLogger(PubKeyPrettyPrint.class);
/*==========================================================
* variables
*==========================================================*/
private X509Key mX509Key = null;
private PrettyPrintFormat pp = null;
/*==========================================================
* constructors
*==========================================================*/
public PubKeyPrettyPrint(PublicKey key) {
if (key instanceof X509Key)
mX509Key = (X509Key) key;
pp = new PrettyPrintFormat(":");
}
/*==========================================================
* public methods
*==========================================================*/
/**
* This method return string representation of the certificate
* in predefined format using specified client local. I18N Support.
*
* @param clientLocale Locale to be used for localization
* @return string representation of the certificate
*/
public String toString(Locale clientLocale, int indentSize, int lineLen) {
if (mX509Key != null)
return X509toString(clientLocale, indentSize, lineLen);
else
return null;
}
public String X509toString(Locale clientLocale, int indentSize, int lineLen) {
//get I18N resources
ResourceBundle resource = ResourceBundle.getBundle(
PrettyPrintResources.class.getName());
StringBuffer sb = new StringBuffer();
try {
String alg = mX509Key.getAlgorithm();
//XXX I18N Algorithm Name ?
sb.append(pp.indent(indentSize) + resource.getString(
PrettyPrintResources.TOKEN_ALGORITHM) +
alg + " - " +
mX509Key.getAlgorithmId().getOID().toString() + "\n");
if (alg.equals("RSA")) {
RSAPublicKey rsakey = new RSAPublicKey(mX509Key.getEncoded());
sb.append(pp.indent(indentSize) + resource.getString(
PrettyPrintResources.TOKEN_PUBLIC_KEY) + "\n");
sb.append(pp.indent(indentSize + 4) + resource.getString(
PrettyPrintResources.TOKEN_PUBLIC_KEY_EXPONENT) +
rsakey.getPublicExponent().toInt() + "\n");
sb.append(pp.indent(indentSize + 4) + resource.getString(
PrettyPrintResources.TOKEN_PUBLIC_KEY_MODULUS) +
"(" + rsakey.getKeySize() + " bits) :\n");
sb.append(pp.toHexString(
rsakey.getModulus().toByteArray(),
indentSize + 8, lineLen));
} else {
// DSAPublicKey is more complicated to decode, since
// the DSAParams (PQG) is not fully decoded.
// So, we just print the entire public key blob
sb.append(pp.indent(indentSize) + resource.getString(
PrettyPrintResources.TOKEN_PUBLIC_KEY) + "\n");
sb.append(pp.toHexString(mX509Key.getKey(), indentSize + 4, lineLen));
}
} catch(InvalidKeyException e){
logger.debug("Impossible convert public certificate to string", e);
}
return sb.toString();
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/util/UniversalCharset.java 0000664 0000000 0000000 00000001131 14565430767 0031513 0 ustar 00root root 0000000 0000000 package org.mozilla.jss.netscape.security.util;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
public class UniversalCharset extends Charset {
public UniversalCharset() {
super("ASN.1-Universal", null);
}
@Override
public boolean contains(Charset cs) {
return false;
}
@Override
public CharsetDecoder newDecoder() {
return new UniversalCharsetDecoder(this);
}
@Override
public CharsetEncoder newEncoder() {
return new UniversalCharsetEncoder(this);
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/util/UniversalCharsetDecoder.java 0000664 0000000 0000000 00000006716 14565430767 0033017 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.util;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CoderResult;
import java.nio.charset.CodingErrorAction;
/**
* Converts bytes in ASN.1 UniversalString character set to UniversalString
* characters.
*
* @author Lily Hsiao
* @author Slava Galperin
*/
public class UniversalCharsetDecoder extends CharsetDecoder {
public UniversalCharsetDecoder(Charset cs) {
super(cs, 0.25f, 1);
}
@Override
protected CoderResult decodeLoop(ByteBuffer in, CharBuffer out) {
while (true) {
// XXX we do not know what to do with truly UCS-4 characters here
// we also assumed network byte order
if (in.remaining() < 4)
return CoderResult.UNDERFLOW;
in.mark();
byte b0 = in.get();
byte b1 = in.get();
byte b2 = in.get();
byte b3 = in.get();
if (CodingErrorAction.REPORT == unmappableCharacterAction() &&
!((b0 == 0 && b1 == 0) || (b2 == 0 && b3 == 0))) {
return CoderResult.unmappableForLength(4);
}
char c;
if (b2 == 0 && b3 == 0) {
// Try to be a bit forgiving. If the byte order is
// reversed, we still try handle it.
// Sample Date Set (1):
// 0000000 f 0 \0 \0 213 0 \0 \0 S 0 \0 \0
// 0000014
// Sample Date Set (2):
// 0000000 w \0 \0 \0 w \0 \0 \0 w \0 \0 \0 . \0 \0 \0
// 0000020 ( \0 \0 \0 t \0 \0 \0 o \0 \0 \0 b \0 \0 \0
// 0000040 e \0 \0 \0 | \0 \0 \0 n \0 \0 \0 o \0 \0 \0
// 0000060 t \0 \0 \0 t \0 \0 \0 o \0 \0 \0 b \0 \0 \0
// 0000100 e \0 \0 \0 ) \0 \0 \0 . \0 \0 \0 c \0 \0 \0
// 0000120 o \0 \0 \0 m \0 \0 \0
// 0000130
c = (char) (((b1 << 8) & 0xff00) + (b0 & 0x00ff));
} else { // (b0 == 0 && b1 == 0)
// This should be the right order.
//
// 0000000 0000 00c4 0000 0064 0000 006d 0000 0069
// 0000020 0000 006e 0000 0020 0000 0051 0000 0041
// 0000040
c = (char) (((b2 << 8) & 0xff00) + (b3 & 0x00ff));
}
if (out.remaining() < 1) {
in.reset();
return CoderResult.OVERFLOW;
}
out.put(c);
}
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/util/UniversalCharsetEncoder.java 0000664 0000000 0000000 00000004132 14565430767 0033017 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.util;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetEncoder;
import java.nio.charset.CoderResult;
/**
* Converts characters in ASN.1 UniversalString character set to UniversalString
* bytes.
*
* @author Lily Hsiao
* @author Slava Galperin
*/
public class UniversalCharsetEncoder extends CharsetEncoder {
public UniversalCharsetEncoder(Charset cs) {
super(cs, 4, 4, new byte[] { 0, 0, 0, 0 });
}
/*
* Converts an array of Unicode characters into an array of UniversalString
* bytes and returns the conversion result.
* @param in input character buffer to convert.
* @param out byte buffer to store output.
* @return encoding result.
*/
@Override
protected CoderResult encodeLoop(CharBuffer in, ByteBuffer out) {
while (true) {
if (in.remaining() < 1)
return CoderResult.UNDERFLOW;
in.mark();
char c = in.get();
if (out.remaining() < 4) {
in.reset();
return CoderResult.OVERFLOW;
}
out.put((byte) 0);
out.put((byte) 0);
out.put((byte) ((c >> 8) & 0xff));
out.put((byte) (c & 0xff));
}
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/util/Utils.java 0000664 0000000 0000000 00000033206 14565430767 0027341 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.util;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.UnknownHostException;
import java.text.SimpleDateFormat;
import java.util.Base64;
import java.util.Date;
import java.util.StringTokenizer;
import java.util.Vector;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class Utils {
private static final Logger logger = LoggerFactory.getLogger(Utils.class);
/**
* Checks if this is NT.
*/
public static boolean isNT() {
return File.separator.equals("\\");
}
public static boolean isUnix() {
return File.separator.equals("/");
}
public static boolean exec(String cmd) {
try {
String cmds[] = null;
if (isNT()) {
// NT
cmds = new String[3];
cmds[0] = "cmd";
cmds[1] = "/c";
cmds[2] = cmd;
} else {
// UNIX
cmds = new String[3];
cmds[0] = "/bin/sh";
cmds[1] = "-c";
cmds[2] = cmd;
}
Process process = Runtime.getRuntime().exec(cmds);
process.waitFor();
if (process.exitValue() == 0) {
/**
* pOut = new BufferedReader(
* new InputStreamReader(process.getInputStream()));
* while ((l = pOut.readLine()) != null) {
* System.out.println(l);
* }
**/
return true;
} else {
/**
* pOut = new BufferedReader(
* new InputStreamReader(process.getErrorStream()));
* l = null;
* while ((l = pOut.readLine()) != null) {
* System.out.println(l);
* }
**/
return false;
}
} catch (IOException e) {
logger.error("The command canot be executed: " + cmd, e);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
return false;
}
public static String readFromStream(InputStream inputStream) throws IOException {
StringBuilder sb = new StringBuilder();
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(inputStream));
String line = null;
while ((line = br.readLine()) != null) {
sb.append(line + System.getProperty("line.separator"));
}
} finally {
br.close();
}
return sb.toString().trim();
}
public static void writeToStream(OutputStream outputStream, String input) throws IOException {
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream));
writer.write(input);
writer.flush();
writer.close();
}
/**
* Utility method to execute system commands
*
* @param cmd The command to be executed and its arguments
* @param input The stdin input to be passed to the cmd
* @return stdout or stderr of the command executed
* @throws IOException
* @throws InterruptedException
*/
public static String exec(String[] cmd, String input) throws IOException, InterruptedException {
ProcessBuilder pb = new ProcessBuilder(cmd);
Process p = pb.start();
if (input != null) {
writeToStream(p.getOutputStream(), input);
}
p.waitFor();
String output;
if (p.exitValue() == 0) {
output = readFromStream(p.getInputStream());
} else {
output = readFromStream(p.getErrorStream());
}
p.destroy();
return output;
}
public static String SpecialURLDecode(String s) {
if (s == null)
return null;
ByteArrayOutputStream out = new ByteArrayOutputStream(s.length());
for (int i = 0; i < s.length(); i++) {
int c = s.charAt(i);
if (c == '+') {
out.write(' ');
} else if (c == '#') {
int c1 = Character.digit(s.charAt(++i), 16);
int c2 = Character.digit(s.charAt(++i), 16);
out.write((char) (c1 * 16 + c2));
} else {
out.write(c);
}
} // end for
return out.toString();
}
public static byte[] SpecialDecode(String s) {
if (s == null)
return null;
ByteArrayOutputStream out = new ByteArrayOutputStream(s.length());
for (int i = 0; i < s.length(); i++) {
int c = s.charAt(i);
if (c == '+') {
out.write(' ');
} else if (c == '#') {
int c1 = Character.digit(s.charAt(++i), 16);
int c2 = Character.digit(s.charAt(++i), 16);
out.write((char) (c1 * 16 + c2));
} else {
out.write(c);
}
} // end for
return out.toByteArray();
}
public static String SpecialEncode(byte data[]) {
StringBuffer sb = new StringBuffer();
for (int i = 0; i < data.length; i++) {
sb.append("%");
if ((data[i] & 0xff) < 16) {
sb.append("0");
}
sb.append(Integer.toHexString((data[i] & 0xff)));
}
return sb.toString().toUpperCase();
}
public static String HexEncode(byte data[]) {
StringBuffer sb = new StringBuffer();
if (data != null) {
for (int i = 0; i < data.length; i++) {
if ((data[i] & 0xff) < 16) {
sb.append("0");
}
sb.append(Integer.toHexString((data[i] & 0xff)));
}
}
return sb.toString();
}
public static void checkHost(String hostname) throws UnknownHostException {
InetAddress.getByName(hostname);
}
public static void copy(String orig, String dest) throws Exception {
try (BufferedReader in = new BufferedReader(new FileReader(orig));
PrintWriter out = new PrintWriter(
new BufferedWriter(new FileWriter(dest)))) {
String line = "";
while (in.ready()) {
line = in.readLine();
if (line != null)
out.println(line);
}
}
}
public static void copyStream(InputStream in, OutputStream out) throws IOException {
byte[] buf = new byte[4096];
int len;
while ((len = in.read(buf)) != -1) {
out.write(buf, 0, len);
}
}
public static void copyStream(BufferedReader in, OutputStreamWriter out) throws IOException {
char[] buf = new char[4096];
int len;
while ((len = in.read(buf)) != -1) {
out.write(buf, 0, len);
}
}
/// Sorts an array of Strings.
// Java currently has no general sort function. Sorting Strings is
// common enough that it's worth making a special case.
public static void sortStrings(String[] strings) {
// Just does a bubblesort.
for (int i = 0; i < strings.length - 1; ++i) {
for (int j = i + 1; j < strings.length; ++j) {
if (strings[i].compareTo(strings[j]) > 0) {
String t = strings[i];
strings[i] = strings[j];
strings[j] = t;
}
}
}
}
/// Returns a date string formatted in Unix ls style - if it's within
// six months of now, Mmm dd hh:ss, else Mmm dd yyyy.
public static String lsDateStr(Date date) {
long dateTime = date.getTime();
if (dateTime == -1L)
return "------------";
long nowTime = System.currentTimeMillis();
SimpleDateFormat formatter = new SimpleDateFormat();
if (Math.abs(nowTime - dateTime) < 183L * 24L * 60L * 60L * 1000L)
formatter.applyPattern("MMM dd hh:ss");
else
formatter.applyPattern("MMM dd yyyy");
return formatter.format(date);
}
/**
* compares contents two byte arrays returning true if exactly same.
*/
static public boolean byteArraysAreEqual(byte[] a, byte[] b) {
if (a.length != b.length)
return false;
for (int i = 0; i < a.length; i++) {
if (a[i] != b[i])
return false;
}
return true;
}
/**
* strips out double quotes around String parameter
*
* @param s the string potentially bracketed with double quotes
* @return string stripped of surrounding double quotes
*/
public static String stripQuotes(String s) {
if (s == null) {
return s;
}
if ((s.startsWith("\"")) && (s.endsWith("\""))) {
return (s.substring(1, (s.length() - 1)));
}
return s;
}
/**
* returns an array of strings from a vector of Strings
* there'll be trouble if the Vector contains something other
* than just Strings
*/
public static String[] getStringArrayFromVector(Vector v) {
String s[] = new String[v.size()];
v.copyInto(s);
return s;
}
/**
* Converts a byte array into a Base-64 encoded string.
* If the chunked option is true, the output will be split into
* multiple lines. Otherwise, the output will be a single line.
*
* @param bytes byte array
* @param chunked generate chunked output
* @return base-64 encoded data
*/
public static String base64encode(byte[] bytes, boolean chunked) {
if (chunked) {
return base64encodeMultiLine(bytes);
} else {
return base64encodeSingleLine(bytes);
}
}
/**
* Converts a byte array into a multi-line Base-64 encoded string.
* Each line is at most 64-character long and terminated with CRLF.
*
* @param bytes byte array
* @return base-64 encoded data
*/
public static String base64encodeMultiLine(byte[] bytes) {
// When switching from apache-commons-codec to the standard library,
// the standard library does not include a final line separator at
// the end of the encoded data. This results in malformed CSRs.
return Base64.getMimeEncoder().encodeToString(bytes) + "\r\n";
}
/**
* Converts a byte array into a single-line Base-64 encoded string.
* The line is not terminated with CRLF.
*
* @param bytes byte array
* @return base-64 encoded data
*/
public static String base64encodeSingleLine(byte[] bytes) {
return Base64.getEncoder().encodeToString(bytes);
}
/**
* Converts a Base-64 encoded string into a byte array.
*
* @param string base-64 encoded data
* @return byte array
*/
public static byte[] base64decode(String string) {
try {
// Java is particular about its base64. We already used the MIME
// decoder as it was most flexible about whitespace. However, it
// doesn't understand URL-encoded Base64 (using '-' instead of
// '+' and '_' instead of '/'). So, detect those characters and
// pass it to the correct decoder.
if (string.contains("_") || string.contains("-")) {
return Base64.getUrlDecoder().decode(string);
} else {
return Base64.getMimeDecoder().decode(string);
}
} catch (IllegalArgumentException iae) {
return new byte[0];
}
}
/**
* Normalize B64 input String
*
* @param string base-64 string
* @return normalized string
*/
public static String normalizeString(String string) {
return normalizeString(string, false);
}
/**
* Normalize B64 input String
*
* @param string base-64 string
* @param keepSpace a boolean variable to control whether to keep spaces or not
* @return normalized string
*/
public static String normalizeString(String string, Boolean keepSpace) {
if (string == null) {
return string;
}
StringBuffer sb = new StringBuffer();
StringTokenizer st = null;
if (keepSpace)
st = new StringTokenizer(string, "\r\n");
else
st = new StringTokenizer(string, "\r\n ");
while (st.hasMoreTokens()) {
String nextLine = st.nextToken();
nextLine = nextLine.trim();
sb.append(nextLine);
}
return sb.toString();
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/util/WrappingParams.java 0000664 0000000 0000000 00000026201 14565430767 0031171 0 ustar 00root root 0000000 0000000 package org.mozilla.jss.netscape.security.util;
import java.security.NoSuchAlgorithmException;
import org.mozilla.jss.asn1.OBJECT_IDENTIFIER;
import org.mozilla.jss.crypto.EncryptionAlgorithm;
import org.mozilla.jss.crypto.IVParameterSpec;
import org.mozilla.jss.crypto.KeyGenAlgorithm;
import org.mozilla.jss.crypto.KeyWrapAlgorithm;
import org.mozilla.jss.crypto.SymmetricKey;
import org.mozilla.jss.crypto.SymmetricKey.Type;
public class WrappingParams {
// session key attributes
SymmetricKey.Type skType;
KeyGenAlgorithm skKeyGenAlgorithm;
int skLength;
// wrapping algorithm for session key
KeyWrapAlgorithm skWrapAlgorithm;
// Encryption algorithm for payload
EncryptionAlgorithm payloadEncryptionAlgorithm;
//wrapping algorithm for payload
KeyWrapAlgorithm payloadWrapAlgorithm;
// payload encryption IV
IVParameterSpec payloadEncryptionIV;
// payload wrapping IV
IVParameterSpec payloadWrappingIV;
public WrappingParams(Type skType, KeyGenAlgorithm skKeyGenAlgorithm, int skLength,
KeyWrapAlgorithm skWrapAlgorithm, EncryptionAlgorithm payloadEncryptionAlgorithm,
KeyWrapAlgorithm payloadWrapAlgorithm, IVParameterSpec payloadEncryptIV, IVParameterSpec payloadWrapIV) {
super();
this.skType = skType;
this.skKeyGenAlgorithm = skKeyGenAlgorithm;
this.skLength = skLength;
this.skWrapAlgorithm = skWrapAlgorithm;
this.payloadEncryptionAlgorithm = payloadEncryptionAlgorithm;
this.payloadWrapAlgorithm = payloadWrapAlgorithm;
this.payloadEncryptionIV = payloadEncryptIV;
this.payloadWrappingIV = payloadWrapIV;
}
public static EncryptionAlgorithm getEncryptionAlgorithmFromName(String name) throws Exception {
String fields[] = name.split("//");
String alg = fields[0];
String mode = fields[1];
String padding = fields[2];
int strength = Integer.parseInt(fields[3]);
return EncryptionAlgorithm.lookup(alg, mode, padding, strength);
}
public WrappingParams() {}
public WrappingParams(String encryptOID, String wrapName, String priKeyAlgo, IVParameterSpec encryptIV, IVParameterSpec wrapIV)
throws NumberFormatException, NoSuchAlgorithmException {
EncryptionAlgorithm encrypt = null;
OBJECT_IDENTIFIER eccOID = new OBJECT_IDENTIFIER("1.2.840.10045.2.1");
if (encryptOID.equals(eccOID.toString())) {
// old CRMFPopClients send this OID for ECC Keys for no apparent reason.
// New clients set this correctly.
// We'll assume the old DES3 wrapping here.
encrypt = EncryptionAlgorithm.DES_CBC_PAD;
} else if (encryptOID.equals(KeyWrapAlgorithm.DES3_CBC_PAD_OID.toString())) {
encrypt = EncryptionAlgorithm.DES3_CBC_PAD;
} else if (encryptOID.equals(KeyWrapAlgorithm.AES_CBC_PAD_OID.toString())) {
encrypt = EncryptionAlgorithm.AES_128_CBC_PAD;
} else {
encrypt = EncryptionAlgorithm.fromOID(new OBJECT_IDENTIFIER(encryptOID));
}
KeyWrapAlgorithm wrap = null;
if (wrapName != null) {
wrap = KeyWrapAlgorithm.fromString(wrapName);
payloadWrapAlgorithm = wrap;
}
switch (encrypt.getAlg().toString()) {
case "AES":
// TODO(alee) - Terrible hack till we figure out why GCM is not working
// or a way to detect the padding.
// We are going to assume AES-128-PAD
encrypt = EncryptionAlgorithm.AES_128_CBC_PAD;
skType = SymmetricKey.AES;
skKeyGenAlgorithm = KeyGenAlgorithm.AES;
if (wrap == null) payloadWrapAlgorithm = KeyWrapAlgorithm.AES_KEY_WRAP_PAD;
break;
case "DESede":
skType = SymmetricKey.DES3;
skKeyGenAlgorithm = KeyGenAlgorithm.DES3;
skWrapAlgorithm = KeyWrapAlgorithm.DES3_CBC_PAD;
if (wrap == null) payloadWrapAlgorithm = KeyWrapAlgorithm.DES3_CBC_PAD;
break;
case "DES":
skType = SymmetricKey.DES;
skKeyGenAlgorithm = KeyGenAlgorithm.DES;
skWrapAlgorithm = KeyWrapAlgorithm.DES3_CBC_PAD;
if (wrap == null) payloadWrapAlgorithm = KeyWrapAlgorithm.DES_CBC_PAD;
break;
default:
throw new NoSuchAlgorithmException("Invalid algorithm");
}
this.skLength = encrypt.getKeyStrength();
if (priKeyAlgo.equals("EC")) {
skWrapAlgorithm = KeyWrapAlgorithm.AES_ECB;
} else {
skWrapAlgorithm = KeyWrapAlgorithm.RSA;
}
payloadEncryptionAlgorithm = encrypt;
payloadEncryptionIV = encryptIV;
if (payloadWrapAlgorithm == KeyWrapAlgorithm.AES_KEY_WRAP_PAD) {
// TODO(alee) Hack -- if we pass in null for the iv in the
// PKIArchiveOptions, we fail to decode correctly when parsing a
// CRMFPopClient request.
payloadWrappingIV = null;
} else {
payloadWrappingIV = wrapIV;
}
}
private WrappingParams(String wrapOID, String priKeyAlgo, IVParameterSpec wrapIV)
throws NumberFormatException, NoSuchAlgorithmException {
KeyWrapAlgorithm kwAlg = KeyWrapAlgorithm.fromOID(wrapOID);
if (kwAlg == KeyWrapAlgorithm.AES_KEY_WRAP_PAD) {
skType = SymmetricKey.AES;
skKeyGenAlgorithm = KeyGenAlgorithm.AES;
payloadWrapAlgorithm = KeyWrapAlgorithm.AES_KEY_WRAP_PAD;
payloadEncryptionAlgorithm = EncryptionAlgorithm.AES_128_CBC_PAD;
skLength = 128;
} else if (kwAlg == KeyWrapAlgorithm.AES_CBC_PAD) {
skType = SymmetricKey.AES;
skKeyGenAlgorithm = KeyGenAlgorithm.AES;
payloadWrapAlgorithm = KeyWrapAlgorithm.AES_CBC_PAD;
payloadEncryptionAlgorithm = EncryptionAlgorithm.AES_128_CBC_PAD;
skLength = 128;
} else if (kwAlg == KeyWrapAlgorithm.DES3_CBC_PAD) {
skType = SymmetricKey.DES3;
skKeyGenAlgorithm = KeyGenAlgorithm.DES3;
skWrapAlgorithm = KeyWrapAlgorithm.DES3_CBC_PAD;
payloadWrapAlgorithm = KeyWrapAlgorithm.DES3_CBC_PAD;
payloadEncryptionAlgorithm = EncryptionAlgorithm.DES3_CBC_PAD;
skLength = payloadEncryptionAlgorithm.getKeyStrength();
} else if (kwAlg == KeyWrapAlgorithm.DES_CBC_PAD) {
skType = SymmetricKey.DES;
skKeyGenAlgorithm = KeyGenAlgorithm.DES;
skWrapAlgorithm = KeyWrapAlgorithm.DES3_CBC_PAD;
payloadWrapAlgorithm = KeyWrapAlgorithm.DES3_CBC_PAD;
payloadEncryptionAlgorithm = EncryptionAlgorithm.DES_CBC_PAD;
skLength = payloadEncryptionAlgorithm.getKeyStrength();
}
if (priKeyAlgo.equals("EC")) {
skWrapAlgorithm = KeyWrapAlgorithm.AES_ECB;
} else {
skWrapAlgorithm = KeyWrapAlgorithm.RSA;
}
// set the IVs
payloadEncryptionIV = wrapIV;
if (payloadWrapAlgorithm == KeyWrapAlgorithm.AES_KEY_WRAP_PAD) {
// TODO(alee) Hack -- if we pass in null for the iv in the
// PKIArchiveOptions, we fail to decode correctly when parsing a
// CRMFPopClient request.
payloadWrappingIV = null;
} else {
payloadWrappingIV = wrapIV;
}
}
public static WrappingParams getWrappingParamsFromArchiveOptions(String wrapOID, String priKeyAlgo, IVParameterSpec wrapIV)
throws NumberFormatException, NoSuchAlgorithmException {
return new WrappingParams(wrapOID, priKeyAlgo, wrapIV);
}
public SymmetricKey.Type getSkType() {
return skType;
}
public void setSkType(SymmetricKey.Type skType) {
this.skType = skType;
}
public void setSkType(String skTypeName) throws NoSuchAlgorithmException {
this.skType = SymmetricKey.Type.fromName(skTypeName);
}
public KeyGenAlgorithm getSkKeyGenAlgorithm() {
return skKeyGenAlgorithm;
}
public void setSkKeyGenAlgorithm(KeyGenAlgorithm skKeyGenAlgorithm) {
this.skKeyGenAlgorithm = skKeyGenAlgorithm;
}
public void setSkKeyGenAlgorithm(String algName) throws NoSuchAlgorithmException {
// JSS mapping is not working. Lets just do something brain-dead to
// handle the cases we expect.
if (algName.equalsIgnoreCase("AES")) {
skKeyGenAlgorithm = KeyGenAlgorithm.AES;
} else if (algName.equalsIgnoreCase("DES")) {
skKeyGenAlgorithm = KeyGenAlgorithm.DES;
} else if (algName.equalsIgnoreCase("DESede")) {
skKeyGenAlgorithm = KeyGenAlgorithm.DES3;
} else if (algName.equalsIgnoreCase("DES3")) {
skKeyGenAlgorithm = KeyGenAlgorithm.DES3;
}
}
public int getSkLength() {
return skLength;
}
public void setSkLength(int skLength) {
this.skLength = skLength;
}
public KeyWrapAlgorithm getSkWrapAlgorithm() {
return skWrapAlgorithm;
}
public void setSkWrapAlgorithm(KeyWrapAlgorithm skWrapAlgorithm) {
this.skWrapAlgorithm = skWrapAlgorithm;
}
public void setSkWrapAlgorithm(String name) throws NoSuchAlgorithmException {
this.skWrapAlgorithm = KeyWrapAlgorithm.fromString(name);
}
public EncryptionAlgorithm getPayloadEncryptionAlgorithm() {
return payloadEncryptionAlgorithm;
}
public void setPayloadEncryptionAlgorithm(EncryptionAlgorithm payloadEncryptionAlgorithm) {
this.payloadEncryptionAlgorithm = payloadEncryptionAlgorithm;
}
public void setPayloadEncryptionAlgorithm(String algName, String modeName, String paddingName, int keyStrength)
throws NoSuchAlgorithmException {
this.payloadEncryptionAlgorithm = EncryptionAlgorithm.lookup(algName, modeName, paddingName, keyStrength);
}
public String getPayloadEncryptionAlgorithmName() {
// work around some of the issues with OIDs in JSS
int strength = payloadEncryptionAlgorithm.getKeyStrength();
String mode = payloadEncryptionAlgorithm.getMode().toString();
String padding = payloadEncryptionAlgorithm.getPadding().toString();
String alg = payloadEncryptionAlgorithm.getAlg().toString();
return alg + "/" + mode + "/" + padding + "/" + Integer.toString(strength);
}
public KeyWrapAlgorithm getPayloadWrapAlgorithm() {
return payloadWrapAlgorithm;
}
public void setPayloadWrapAlgorithm(KeyWrapAlgorithm payloadWrapAlgorithm) {
this.payloadWrapAlgorithm = payloadWrapAlgorithm;
}
public void setPayloadWrapAlgorithm(String name) throws NoSuchAlgorithmException {
this.payloadWrapAlgorithm = KeyWrapAlgorithm.fromString(name);
}
public IVParameterSpec getPayloadEncryptionIV() {
return payloadEncryptionIV;
}
public void setPayloadEncryptionIV(IVParameterSpec payloadEncryptionIV) {
this.payloadEncryptionIV = payloadEncryptionIV;
}
public IVParameterSpec getPayloadWrappingIV() {
return payloadWrappingIV;
}
public void setPayloadWrappingIV(IVParameterSpec payloadWrappingIV) {
this.payloadWrappingIV = payloadWrappingIV;
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509/ 0000775 0000000 0000000 00000000000 14565430767 0025122 5 ustar 00root root 0000000 0000000 jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509/ACertAttrSet.java 0000664 0000000 0000000 00000010654 14565430767 0030300 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.x509;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.cert.CertificateException;
import java.util.Enumeration;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
/**
* A plain certattr set used by pkcs10 to parse an unknown attribute.
*
* @author Lily Hsiao
*/
public class ACertAttrSet implements CertAttrSet {
protected DerValue mDerValue = null;
public ACertAttrSet(DerValue derValue) throws IOException {
mDerValue = derValue;
}
public DerValue getDerValue() {
return mDerValue;
}
/**
* Returns a short string describing this certificate attribute.
*
* @return value of this certificate attribute in
* printable form.
*/
@Override
public String toString() {
return "ACertAttrSet value " + (mDerValue == null ? "null" : "not null");
}
/**
* Encodes the attribute to the output stream in a format
* that can be parsed by the decode
method.
*
* @param out the OutputStream to encode the attribute to.
*
* @exception CertificateException on encoding or validity errors.
* @exception IOException on other errors.
*/
@Override
public void encode(OutputStream out)
throws CertificateException, IOException {
mDerValue.encode((DerOutputStream) out);
}
/**
* Decodes the attribute in the input stream.
*
* @param in the InputStream to read the encoded attribute from.
*
* @exception CertificateException on decoding or validity errors.
* @exception IOException on other errors.
*/
@Override
public void decode(InputStream in)
throws CertificateException, IOException {
throw new IOException("not supported");
}
/**
* Sets an attribute value within this CertAttrSet.
*
* @param name the name of the attribute (e.g. "x509.info.key")
* @param obj the attribute object.
*
* @exception CertificateException on attribute handling errors.
* @exception IOException on other errors.
*/
@Override
public void set(String name, Object obj)
throws CertificateException, IOException {
throw new IOException("not supported");
}
/**
* Gets an attribute value for this CertAttrSet.
*
* @param name the name of the attribute to return.
*
* @exception CertificateException on attribute handling errors.
* @exception IOException on other errors.
*/
@Override
public Object get(String name)
throws CertificateException, IOException {
throw new IOException("not supported");
}
/**
* Deletes an attribute value from this CertAttrSet.
*
* @param name the name of the attribute to delete.
*
* @exception CertificateException on attribute handling errors.
* @exception IOException on other errors.
*/
@Override
public void delete(String name)
throws CertificateException, IOException {
throw new IOException("not supported");
}
/**
* Returns an enumeration of the names of the attributes existing within
* this attribute.
*
* @return an enumeration of the attribute names.
*/
@Override
public Enumeration getAttributeNames() {
return null;
}
/**
* Returns the name (identifier) of this CertAttrSet.
*
* @return the name of this CertAttrSet.
*/
@Override
public String getName() {
return "Generic Extension";
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509/AVA.java 0000664 0000000 0000000 00000023634 14565430767 0026404 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.x509;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.StandardCharsets;
import java.nio.charset.UnsupportedCharsetException;
import org.mozilla.jss.netscape.security.util.DerEncoder;
import org.mozilla.jss.netscape.security.util.DerInputStream;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
import org.mozilla.jss.netscape.security.util.ObjectIdentifier;
/**
* X.500 Attribute-Value-Assertion (AVA): an attribute, as identified by
* some attribute ID, has some particular value. Values are as a rule ASN.1
* printable strings. A conventional set of type IDs is recognized when
* parsing (and generating) RFC 1779 syntax strings.
*
*
* AVAs are components of X.500 relative names. Think of them as being individual fields of a database record. The
* attribute ID is how you identify the field, and the value is part of a particular record.
*
* @see X500Name
* @see RDN
* @see LdapDNStrConverter
*
* @version 1.14
*
* @author David Brownell
* @author Amit Kapoor
* @author Hemma Prafullchandra
*/
// public ... when RDN is public and X.500Names can be
// constructed using RDNs, and all three classes are cleaner
public final class AVA implements DerEncoder {
ObjectIdentifier oid;
DerValue value;
/**
* Constructs an AVA from a Ldap DN string with one AVA component
* using the global default LdapDNStrConverter.
*
* @see LdapDNStrConverter
* @param avaString a Ldap DN string with one AVA component.
*/
public AVA(String avaString)
throws IOException {
AVA ava;
ava = LdapDNStrConverter.getDefault().parseAVA(avaString);
oid = ava.getOid();
value = ava.getValue();
}
/**
* Like AVA(String) with a DER encoding order given for Directory Strings.
*/
public AVA(String avaString, byte[] tags)
throws IOException {
AVA ava;
ava = LdapDNStrConverter.getDefault().parseAVA(avaString, tags);
oid = ava.getOid();
value = ava.getValue();
}
/**
* Constructs an AVA from a Ldap DN string containing one AVA
* component using the specified LdapDNStrConverter.
*
* @see LdapDNStrConverter
* @param avaString a Ldap DN string containing one AVA.
* @param ldapDNStrConverter a LdapDNStrConverter
*/
public AVA(String avaString, LdapDNStrConverter ldapDNStrConverter)
throws IOException {
AVA ava;
ava = ldapDNStrConverter.parseAVA(avaString);
oid = ava.getOid();
value = ava.getValue();
}
/**
* Constructs an AVA from an OID and DerValue.
*
* @param type an ObjectIdentifier
* @param val a DerValue
*/
public AVA(ObjectIdentifier type, DerValue val) {
oid = type;
value = val;
}
/**
* Constructs an AVA from an input stream of UTF8 bytes that form
* a Ldap DN string. Then parse the Ldap DN string using the global
* default LdapDNStrConverter.
* Parses an RFC 1779 style AVA string: CN=fee fie foe fum
* or perhaps with quotes. Not all defined AVA tags are supported;
* of current note are X.400 related ones (PRMD, ADMD, etc).
*
* This terminates at unescaped AVA separators ("+") or RDN
* separators (",", ";"), or DN terminators {@literal (">")}, and removes
* cosmetic whitespace at the end of values.
*
* @see LdapDNStrConverter
* @param in the input stream.
*/
public AVA(InputStream in) throws IOException {
try {
// convert from UTF8 bytes to java string then parse it.
byte[] buffer = new byte[in.available()];
if (in.read(buffer) > 0) {
Charset charset = StandardCharsets.UTF_8;
CharsetDecoder decoder = charset.newDecoder();
CharBuffer charBuffer = decoder.decode(ByteBuffer.wrap(buffer));
AVA a = LdapDNStrConverter.getDefault().parseAVA(charBuffer.toString());
oid = a.getOid();
value = a.getValue();
}
} catch (UnsupportedCharsetException e) {
throw new IOException("UTF8 encoding not supported", e);
}
}
/**
* Constructs an AVA from a Der Input Stream.
*
* @param in the Der Input Stream.
*/
public AVA(DerInputStream in) throws IOException {
DerValue assertion = in.getDerValue();
/*
* Individual attribute value assertions are SEQUENCE of two values.
* That'd be a "struct" outside of ASN.1.
*/
if (assertion.tag != DerValue.tag_Sequence)
throw new CertParseError("X500 AVA, not a sequence");
ObjectIdentifier o = assertion.data.getOID();
oid = X500NameAttrMap.getDefault().getOid(o);
if (oid == null) {
// NSCP #329837
// if this OID is not recongized in our map (table),
// it is fine. we just store it as regular OID.
oid = o;
}
value = assertion.data.getDerValue();
if (assertion.data.available() != 0)
throw new CertParseError("AVA, extra bytes = "
+ assertion.data.available());
}
// other public methods.
/**
* Returns true if another AVA has the same OID and DerValue.
*
* @param other the other AVA.
* @return ture iff other AVA has same oid and value.
*/
public boolean equals(AVA other) {
return oid.equals(other.oid) && value.equals(other.value);
}
/**
* Compares the AVA with an Object, returns true if the object is
* an AVA and has the same OID and value.
*
* @param other the other object.
* @return true iff other object is an AVA and has same oid and value.
*/
@Override
public boolean equals(Object other) {
return other instanceof AVA ava && equals(ava);
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((oid == null) ? 0 : oid.hashCode());
result = prime * result + ((value == null) ? 0 : value.hashCode());
return result;
}
/**
* Encodes the AVA to a Der output stream.
* AVAs are encoded as a SEQUENCE of two elements.
*
* @param out The Der output stream.
*/
public void encode(DerOutputStream out) throws IOException {
derEncode(out);
}
/**
* DER encode this object onto an output stream.
* Implements the DerEncoder
interface.
*
* @param out
* the output stream on which to write the DER encoding.
*
* @exception IOException on encoding error.
*/
@Override
public void derEncode(OutputStream out) throws IOException {
try (DerOutputStream tmp2 = new DerOutputStream()) {
DerOutputStream tmp = new DerOutputStream();
tmp.putOID(oid);
value.encode(tmp);
tmp2.write(DerValue.tag_Sequence, tmp);
out.write(tmp2.toByteArray());
}
}
/**
* Returns a Ldap DN string with one AVA component using
* the global default LdapDNStrConverter.
*
* @return a Ldap DN string
* @exception IOException if an error occurs during conversion.
* @see LdapDNStrConverter
*/
public String toLdapDNString()
throws IOException {
LdapDNStrConverter v = LdapDNStrConverter.getDefault();
return v.encodeAVA(this);
}
/**
* Returns a Ldap DN string with one AVA component using the specified
* LdapDNStrConverter.
*
* @return a Ldap DN string
* @param ldapDNStrConverter a Ldap DN String Converter
* @exception IOException if an error occurs during the conversion.
* @see LdapDNStrConverter
*/
public String toLdapDNString(LdapDNStrConverter ldapDNStrConverter)
throws IOException {
return ldapDNStrConverter.encodeAVA(this);
}
/**
* Returns a Ldap DN string with the AVA component using the global
* default LdapDNStrConverter, or null if an error occurs in conversion.
*
* @return a Ldap DN string containing the AVA, or null if an
* error occurs in the conversion.
*/
@Override
public String toString() {
String s;
try {
// NOTE that a LdapDNString is returned here to match the
// original source from sun. Could also return the raw value
// (before Ldap escaping) here.
s = toLdapDNString();
} catch (IOException e) {
return "";
}
return s;
}
/**
* Returns the OID in the AVA.
*
* @return the ObjectIdentifier in this AVA.
*/
public ObjectIdentifier getOid() {
return oid;
}
/**
* Returns the value in this AVA as a DerValue
*
* @return attribute value in this AVA.
*/
public DerValue getValue() {
return value;
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509/AVAValueConverter.java 0000664 0000000 0000000 00000006175 14565430767 0031272 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.x509;
import java.io.IOException;
import org.mozilla.jss.netscape.security.util.DerValue;
/**
* Interface for classes that convert a attribute value string to a
* DER encoded ASN.1 value and vice versa.
* The converters are associated with attribute types, such as
* directory string, ia5string, etc.
*
*
* For example, to convert a string, such as an organization name for the "O" attribute to a DerValue, the "O" attribute
* is mapped to the DirStrConverter which is used to convert the organization name to a DER encoded Directory String
* which is a DerValue of a ASN.1 PrintableString, T.61String or UniversalString for the organization name.
*
* @author Lily Hsiao, Slava Galperin at Netscape Communications, Inc.
*/
public interface AVAValueConverter {
/**
* Converts a string to a DER encoded attribute value.
*
* @param valueString An AVA value string not encoded in any form.
*
* @return A DerValue object.
*
* @exception IOException if an error occurs during the conversion.
*/
public DerValue getValue(String valueString)
throws IOException;
/**
* Converts a string to a DER encoded attribute value.
* Specify the order of DER tags to use if more than one encoding is
* possible. Currently Directory Strings can have different order
* for backwards compatibility. By 2003 all should be UTF8String.
*
* @param valueString An AVA value string not encoded in any form.
*
* @return A DerValue object.
*
* @exception IOException if an error occurs during the conversion.
*/
public DerValue getValue(String valueString, byte[] tags)
throws IOException;
/**
* Converts a BER encoded value to a DER encoded attribute value.
*
* @param berStream A byte array of the BER encoded AVA value.
* @return A DerValue object.
*/
public DerValue getValue(byte[] berStream)
throws IOException;
/**
* Converts a DER encoded value to a string, not encoded in any form.
*
* @param avaValue A DerValue object.
*
* @return A string for the value or null if it can't be converted.
*
* @exception IOException if an error occurs during the conversion.
*/
public String getAsString(DerValue avaValue)
throws IOException;
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509/AlgIdDSA.java 0000664 0000000 0000000 00000015326 14565430767 0027304 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.x509;
import java.io.IOException;
import java.math.BigInteger;
import java.security.ProviderException;
import java.security.interfaces.DSAParams;
import org.mozilla.jss.netscape.security.util.BigInt;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
/**
* This class identifies DSS/DSA Algorithm variants, which are distinguished
* by using different algorithm parameters P, Q, G. It uses the
* NIST/IETF standard DER encoding. These are used to implement the Digital
* Signature Standard (DSS), FIPS 186.
*
*
* NOTE: At this time, DSS/DSA Algorithm IDs must always
* include these parameters. Use of DSS/DSA in modes where parameters are
* either implicit (e.g. a default applicable to a site or a larger scope),
* or are derived from some Certificate Authority's DSS certificate, is
* not currently supported.
*
* @version 1.31
* @author David Brownell
*/
public final class AlgIdDSA extends AlgorithmId implements DSAParams {
/**
*
*/
private static final long serialVersionUID = 5978220691806461631L;
/*
* The three unsigned integer parameters.
*/
private BigInteger p, q, g;
/** Returns the DSS/DSA parameter "P" */
@Override
public BigInteger getP() {
return p;
}
/** Returns the DSS/DSA parameter "Q" */
@Override
public BigInteger getQ() {
return q;
}
/** Returns the DSS/DSA parameter "G" */
@Override
public BigInteger getG() {
return g;
}
AlgIdDSA(DerValue val) throws IOException {
super(val.getOID());
}
/**
* Construct an AlgIdDSA from an X.509 encoded byte array.
* @param encodedAlg byte array
*/
public AlgIdDSA(byte[] encodedAlg) throws IOException {
super(new DerValue(encodedAlg).getOID());
}
/**
* Constructs a DSS/DSA Algorithm ID from unsigned integers that
* define the algorithm parameters. Those integers are encoded
* as big-endian byte arrays.
*
* @param p the DSS/DSA paramter "P"
* @param q the DSS/DSA paramter "Q"
* @param g the DSS/DSA paramter "G"
*/
public AlgIdDSA(byte p[], byte q[], byte g[])
throws IOException {
this(new BigInteger(1, p),
new BigInteger(1, q),
new BigInteger(1, g));
}
/**
* Constructs a DSS/DSA Algorithm ID from numeric parameters.
*
* @param p the DSS/DSA paramter "P"
* @param q the DSS/DSA paramter "Q"
* @param g the DSS/DSA paramter "G"
*/
public AlgIdDSA(BigInteger p, BigInteger q, BigInteger g) {
super(DSA_oid);
try {
this.p = p;
this.q = q;
this.g = g;
initializeParams();
} catch (IOException e) {
/* this should not happen */
throw new ProviderException("Construct DSS/DSA Algorithm ID");
}
}
/**
* Returns "DSA", indicating the Digital Signature Algorithm (DSA) as
* defined by the Digital Signature Standard (DSS), FIPS 186.
*/
@Override
public String getName() {
return "DSA";
}
/*
* For algorithm IDs which haven't been created from a DER encoded
* value, "params" must be created.
*/
private void initializeParams()
throws IOException {
try (DerOutputStream out = new DerOutputStream()) {
out.putInteger(new BigInt(p.toByteArray()));
out.putInteger(new BigInt(q.toByteArray()));
out.putInteger(new BigInt(g.toByteArray()));
params = new DerValue(DerValue.tag_Sequence, out.toByteArray());
}
}
/**
* Parses algorithm parameters P, Q, and G. They're found
* in the "params" member, which never needs to be changed.
*/
@Override
protected void decodeParams()
throws IOException {
if (params == null || params.tag != DerValue.tag_Sequence)
throw new IOException("DSA alg parsing error");
params.data.reset();
this.p = params.data.getInteger().toBigInteger();
this.q = params.data.getInteger().toBigInteger();
this.g = params.data.getInteger().toBigInteger();
if (params.data.available() != 0)
throw new IOException("AlgIdDSA params, extra=" +
params.data.available());
}
/*
* Returns a formatted string describing the parameters.
*/
@Override
public String toString() {
return paramsToString();
}
/*
* Returns a string describing the parameters.
*/
@Override
protected String paramsToString() {
return "\n p:\n" + (new BigInt(p)).toString() +
"\n q:\n" + (new BigInt(q)).toString() +
"\n g:\n" + (new BigInt(g)).toString() +
"\n";
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((g == null) ? 0 : g.hashCode());
result = prime * result + ((p == null) ? 0 : p.hashCode());
result = prime * result + ((q == null) ? 0 : q.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
AlgIdDSA other = (AlgIdDSA) obj;
if (g == null) {
if (other.g != null)
return false;
} else if (!g.equals(other.g))
return false;
if (p == null) {
if (other.p != null)
return false;
} else if (!p.equals(other.p))
return false;
if (q == null) {
if (other.q != null)
return false;
} else if (!q.equals(other.q))
return false;
return true;
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509/AlgorithmId.java 0000664 0000000 0000000 00000120545 14565430767 0030177 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.x509;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Serializable;
import java.security.AlgorithmParameters;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.spec.InvalidParameterSpecException;
import java.security.spec.MGF1ParameterSpec;
import java.security.spec.PSSParameterSpec;
import org.apache.commons.lang3.ArrayUtils;
import org.mozilla.jss.netscape.security.util.DerEncoder;
import org.mozilla.jss.netscape.security.util.DerInputStream;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
import org.mozilla.jss.netscape.security.util.ObjectIdentifier;
/**
* This class identifies algorithms, such as cryptographic transforms, each
* of which may be associated with parameters. Instances of this base class
* are used when this runtime environment has no special knowledge of the
* algorithm type, and may also be used in other cases. Equivalence is
* defined according to OID and (where relevant) parameters.
*
*
* Subclasses may be used, for example when when the algorithm ID has associated parameters which some code (e.g. code
* using public keys) needs to have parsed. Two examples of such algorithms are Diffie-Hellman key exchange, and the
* Digital Signature Standard Algorithm (DSS/DSA).
*
*
* The OID constants defined in this class correspond to some widely used algorithms, for which conventional string
* names have been defined. This class is not a general repository for OIDs, or for such string names. Note that the
* mappings between algorithm IDs and algorithm names is not one-to-one.
*
* @version 1.70
*
* @author David Brownell
* @author Amit Kapoor
* @author Hemma Prafullchandra
*/
public class AlgorithmId implements Serializable, DerEncoder {
/** use serialVersionUID from JDK 1.1. for interoperability */
private static final long serialVersionUID = 7205873507486557157L;
/**
* The object identitifer being used for this algorithm.
*/
private ObjectIdentifier algid = null;
// The (parsed) parameters
private AlgorithmParameters algParams = null;
// Use this for the various flavors of the RSA PSS alg.
private String cachedAlgName = null;
/**
* Parameters for this algorithm. These are stored in unparsed
* DER-encoded form; subclasses can be made to automaticaly parse
* them so there is fast access to these parameters.
*/
protected DerValue params = null;
protected String paramsString = null;
public AlgorithmParameters getParameters() {
return this.algParams;
}
public String getParametersString() {
return this.paramsString;
}
public void setParametersString(String paramStr) {
this.paramsString = paramStr;
}
/**
* Returns one of the algorithm IDs most commonly associated
* with this algorithm name.
*
* @param algname the name being used
* @return an ID for the algorithm.
* @exception NoSuchAlgorithmException on error.
*/
public static AlgorithmId get(String algname)
throws NoSuchAlgorithmException {
ObjectIdentifier oid = algOID(algname);
if (oid == null)
throw new NoSuchAlgorithmException("unrecognized algorithm name: " + algname);
try {
return new AlgorithmId(oid, algname);
} catch (Exception e) {
throw new NoSuchAlgorithmException(e);
}
}
/**
* Parse (unmarshal) an ID from a DER sequence input value. This form
* parsing might be used when expanding a value which has already been
* partially unmarshaled as a set or sequence member.
*
* @exception IOException on error.
* @param val the input value, which contains the algid and, if
* there are any parameters, those parameters.
* @return an ID for the algorithm. If the system is configured
* appropriately, this may be an instance of a class
* with some kind of special support for this algorithm.
* In that case, you may "narrow" the type of the ID.
*/
public static AlgorithmId parse(DerValue val)
throws IOException {
if (val.tag != DerValue.tag_Sequence)
throw new IOException("algid parse error, not a sequence");
/*
* Get the algorithm ID and any parameters.
*/
ObjectIdentifier algid;
DerValue params;
DerInputStream in = val.toDerInputStream();
algid = in.getOID();
if (in.available() == 0)
params = null;
else {
params = in.getDerValue();
if (params.tag == DerValue.tag_Null)
params = null;
}
/*
* Figure out what class (if any) knows about this oid's
* parameters. Make one, and give it the data to decode.
*/
AlgorithmId alg = null;
// omit parameter field for ECDSA
if (!algid.equals(sha224WithEC_oid) &&
!algid.equals(sha256WithEC_oid) &&
!algid.equals(sha384WithEC_oid) &&
!algid.equals(sha512WithEC_oid)) {
alg = new AlgorithmId(algid, params);
} else {
try {
alg = new AlgorithmId(algid);
} catch (Exception e) {
throw new IOException(e);
}
}
if (params != null)
alg.decodeParams();
/*
* Set the raw params string in case
* higher level code might want the info
*/
String paramStr = null;
if (params != null) {
paramStr = params.toString();
}
alg.setParametersString(paramStr);
return alg;
}
public static AlgorithmId parse(byte[] val)
throws IOException {
return null;
}
/**
* Constructs an algorithm ID with a fully encoded params object
* @param oid the identifier for the algorithm
* @param params the fully encoded AlgorithmIdentifier Object
* @throws NoSuchAlgorithmException
* @throws IOException
*/
public AlgorithmId(ObjectIdentifier oid, AlgorithmParameters params)
throws IOException, NoSuchAlgorithmException {
algid = oid;
algParams = params;
if (algParams == null) {
throw new NoSuchAlgorithmException("AlgorithmId: null algParams.");
}
this.params = new DerValue(algParams.getEncoded());
}
/**
* Constructor that takes the oid and name, so the name can be cachedf or laster use.
* @param oid the identifier for the algorithm
* @param algName the algorithm name
* @throws NoSuchAlgorithmException
* @throws IOException
*
*/
public AlgorithmId(ObjectIdentifier oid, String algName)
throws IOException, NoSuchAlgorithmException {
algid = oid;
cachedAlgName = algName;
/* Create the params if our algorithm is RSA PSS related */
if (algName != null && algName.contains("PSS")) {
this.algParams = getPSSParams(algName);
this.params = new DerValue(this.algParams.getEncoded());
}
}
/**
* Constructs an algorithm ID with possible RSAPSS params.
*
* @param oid the identifier for the algorithm
*/
public AlgorithmId(ObjectIdentifier oid) {
algid = oid;
String algName = algName();
/* Create the params if our algorithm is RSA PSS related */
if (algName != null && algName.contains("PSS")) {
try {
this.algParams = getPSSParams(algName);
if (this.algParams != null) {
try {
this.params = new DerValue(this.algParams.getEncoded());
} catch (IOException e) {
throw new IOException(e);
}
}
} catch (Exception e) {
//Preserve original signature...
throw new RuntimeException("Unable to create pssPrams in Algorithmid(ObjectIdentifier oid): " + e.getMessage(), e);
}
}
}
private AlgorithmParameters getPSSParams(String algName)
throws NoSuchAlgorithmException, IOException {
cachedAlgName = algName;
AlgorithmParameters ret = null;
/* Create the params if our algorithm is RSA PSS related */
try {
ret = createPSSAlgorithmParameters(algName);
} catch (Exception e) {
throw new NoSuchAlgorithmException(e);
}
return ret;
}
private AlgorithmId(ObjectIdentifier oid, DerValue params)
throws IOException {
this.algid = oid;
this.params = params;
if (this.params != null)
decodeParams();
}
/**
* Constructs an algorithm ID which will be initialized
* separately, for example by deserialization.
*
* @deprecated use one of the other constructors.
*/
@Deprecated
public AlgorithmId() {
}
protected void decodeParams() throws IOException {
try {
if (algid.equals(AlgorithmId.rsaPSS_oid)) {
try {
this.algParams = createPSSAlgorithmParametersFromData(this.params.toByteArray());
return;
} catch (Exception e) {
throw new IOException(e);
}
}
this.algParams = AlgorithmParameters.getInstance(this.algid.toString());
} catch (NoSuchAlgorithmException e) {
/*
* This algorithm parameter type is not supported, so we cannot
* parse the parameters.
*/
this.algParams = null;
return;
}
// Decode (parse) the parameters
this.algParams.init(this.params.toByteArray());
}
/**
* Marshal a DER-encoded "AlgorithmID" sequence on the DER stream.
* @param out the output stream on which to write the DER encoding.
* @exception IOException on encoding error.
*/
public final void encode(DerOutputStream out)
throws IOException {
derEncode(out);
}
/**
* DER encode this object onto an output stream.
* Implements the DerEncoder
interface.
* @param out the output stream on which to write the DER encoding.
*
* @exception IOException on encoding error.
*/
@Override
public void derEncode(OutputStream out) throws IOException {
try (DerOutputStream tmp = new DerOutputStream()) {
DerOutputStream bytes = new DerOutputStream();
bytes.putOID(algid);
// omit parameter field for ECDSA
if (!algid.equals(sha224WithEC_oid) &&
!algid.equals(sha256WithEC_oid) &&
!algid.equals(sha384WithEC_oid) &&
!algid.equals(sha512WithEC_oid)) {
if (params == null) {
bytes.putNull();
} else
bytes.putDerValue(params);
}
tmp.write(DerValue.tag_Sequence, bytes);
out.write(tmp.toByteArray());
}
}
/**
* DER encode this object onto an output stream.
* Implements the DerEncoder
interface.
*
* @param out the output stream on which to write the DER encoding params,
* using context value.
* @param contextVal context value
*
* @exception IOException on encoding error.
*/
public void derEncodeWithContext(OutputStream out, int contextVal) throws IOException {
try (DerOutputStream tmp = new DerOutputStream()) {
DerOutputStream bytes = new DerOutputStream();
bytes.putOID(algid);
byte val = (byte) contextVal;
// omit parameter field for ECDSA
if (!algid.equals(sha224WithEC_oid) &&
!algid.equals(sha256WithEC_oid) &&
!algid.equals(sha384WithEC_oid) &&
!algid.equals(sha512WithEC_oid)) {
if (params == null) {
bytes.putNull();
} else {
bytes.putDerValue(params);
}
}
DerOutputStream seq = new DerOutputStream();
seq.write(DerValue.tag_Sequence, bytes);
tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, val), seq);
out.write(tmp.toByteArray());
}
}
// XXXX cleaning required
/**
* Returns the DER-encoded X.509 AlgorithmId as a byte array.
* @return the byte array
* @throws IOException If an error occurred.
*/
public final byte[] encode() throws IOException {
try (DerOutputStream out = new DerOutputStream()) {
DerOutputStream bytes = new DerOutputStream();
bytes.putOID(algid);
// omit parameter field for ECDSA
if (!algid.equals(sha224WithEC_oid) &&
!algid.equals(sha256WithEC_oid) &&
!algid.equals(sha384WithEC_oid) &&
!algid.equals(sha512WithEC_oid)) {
if (params == null) {
bytes.putNull();
} else
bytes.putDerValue(params);
}
out.write(DerValue.tag_Sequence, bytes);
return out.toByteArray();
}
}
/**
* Returns list of signing algorithms for a key algorithm such as
* RSA or DSA.
* @param alg key algorithm
* @return list of signing algorithms
*/
public static String[] getSigningAlgorithms(AlgorithmId alg) {
ObjectIdentifier algOid = alg.getOID();
if (algOid.equals(DSA_oid) || algOid.equals(DSA_OIW_oid)) {
return DSA_SIGNING_ALGORITHMS;
} else if (algOid.equals(RSA_oid) || algOid.equals(RSAEncryption_oid)) {
return RSA_SIGNING_ALGORITHMS;
} else if (algOid.equals(ANSIX962_EC_Public_Key_oid) || algOid.equals(ANSIX962_SHA1_With_EC_oid)) {
return EC_SIGNING_ALGORITHMS;
} else {
return null;
}
}
/*
* Translates from some common algorithm names to the
* OID with which they're usually associated ... this mapping
* is the reverse of the one below, except in those cases
* where synonyms are supported or where a given algorithm
* is commonly associated with multiple OIDs.
*/
private static ObjectIdentifier algOID(String name) {
// Digesting algorithms
if (name.equals("MD5"))
return AlgorithmId.MD5_oid;
if (name.equals("MD2"))
return AlgorithmId.MD2_oid;
if (name.equals("SHA") || name.equals("SHA1")
|| name.equals("SHA-1"))
return AlgorithmId.SHA_oid;
if (name.equals("SHA256") || name.equals("SHA-256"))
return AlgorithmId.SHA256_oid;
if (name.equals("SHA512") || name.equals("SHA-512"))
return AlgorithmId.SHA512_oid;
// Various public key algorithms
if (name.equals("RSA"))
return AlgorithmId.RSA_oid;
if (name.equals("RSAEncryption"))
return AlgorithmId.RSAEncryption_oid;
if (name.equals("Diffie-Hellman") || name.equals("DH"))
return AlgorithmId.DH_oid;
if (name.equals("DSA"))
return AlgorithmId.DSA_oid;
// Common signature types
if (name.equals("SHA1withEC") || name.equals("SHA1/EC")
|| name.equals("1.2.840.10045.4.1"))
return AlgorithmId.sha1WithEC_oid;
if (name.equals("SHA224withEC") || name.equals("SHA224/EC")
|| name.equals("1.2.840.10045.4.3.1"))
return AlgorithmId.sha224WithEC_oid;
if (name.equals("SHA256withEC") || name.equals("SHA256/EC")
|| name.equals("1.2.840.10045.4.3.2"))
return AlgorithmId.sha256WithEC_oid;
if (name.equals("SHA384withEC") || name.equals("SHA384/EC")
|| name.equals("1.2.840.10045.4.3.3"))
return AlgorithmId.sha384WithEC_oid;
if (name.equals("SHA512withEC") || name.equals("SHA512/EC")
|| name.equals("1.2.840.10045.4.3.4"))
return AlgorithmId.sha512WithEC_oid;
if (name.equals("SHA1withRSA") || name.equals("SHA1/RSA")
|| name.equals("1.2.840.113549.1.1.5"))
return AlgorithmId.sha1WithRSAEncryption_oid;
if (name.equals("SHA256withRSA") || name.equals("SHA256/RSA")
|| name.equals("1.2.840.113549.1.1.11"))
return AlgorithmId.sha256WithRSAEncryption_oid;
if (name.equals("SHA384withRSA") || name.equals("SHA384/RSA")
|| name.equals("1.2.840.113549.1.1.12"))
return AlgorithmId.sha384WithRSAEncryption_oid;
if (name.equals("SHA512withRSA") || name.equals("SHA512/RSA")
|| name.equals("1.2.840.113549.1.1.13"))
return AlgorithmId.sha512WithRSAEncryption_oid;
if (name.equals("MD5withRSA") || name.equals("MD5/RSA"))
return AlgorithmId.md5WithRSAEncryption_oid;
if (name.equals("MD2withRSA") || name.equals("MD2/RSA"))
return AlgorithmId.md2WithRSAEncryption_oid;
if (name.equals("SHAwithDSA") || name.equals("SHA1withDSA")
|| name.equals("SHA/DSA") || name.equals("SHA1/DSA"))
return AlgorithmId.sha1WithDSA_oid;
if (name.equals("SHA256withRSA/PSS") || name.equals("SHA384withRSA/PSS") || name.equals("SHA512withRSA/PSS"))
return AlgorithmId.rsaPSS_oid;
return null;
}
/*
* For the inevitable cases where key or signature types are not
* configured in an environment which encounters such keys or
* signatures, we still attempt to provide user-friendly names
* for some of the most common algorithms. Subclasses can of
* course override getName().
*
* Wherever possible, the names are those defined by the IETF.
* Such names are noted below.
*/
private String algName() {
// Common message digest algorithms
if (algid.equals(AlgorithmId.MD5_oid))
return "MD5"; // RFC 1423
if (algid.equals(AlgorithmId.MD2_oid))
return "MD2"; // RFC 1423
if (algid.equals(AlgorithmId.SHA_oid))
return "SHA";
if (algid.equals(AlgorithmId.SHA256_oid))
return "SHA256";
if (algid.equals(AlgorithmId.SHA384_oid))
return "SHA384";
if (algid.equals(AlgorithmId.SHA512_oid))
return "SHA512";
if (algid.equals(AlgorithmId.rsaPSS_oid)) {
if (cachedAlgName != null) {
return cachedAlgName;
}
// Get alg variant from params info
String paramStr = paramsToString();
if (paramStr != null) {
if (paramStr.contains("HashAlg: SHA-256")) {
cachedAlgName = "SHA256withRSA/PSS";
} else if (paramStr.contains("HashAlg: SHA-384")) {
cachedAlgName = "SHA384withRSA/PSS";
} else if (paramStr.contains("HashAlg: SHA-512")) {
cachedAlgName = "SHA512withRSA/PSS";
} else {
throw new RuntimeException("Unknown or unsupported signature algorithm in PSS parameters: " + paramStr);
}
}
return cachedAlgName;
}
// Common key types
if (algid.equals(AlgorithmId.ANSIX962_EC_Public_Key_oid))
return "EC";
if (algid.equals(AlgorithmId.RSAEncryption_oid)
|| algid.equals(AlgorithmId.RSA_oid))
return "RSA";
if (algid.equals(AlgorithmId.DH_oid)
|| algid.equals(AlgorithmId.DH_PKIX_oid))
return "Diffie-Hellman";
if (algid.equals(AlgorithmId.DSA_oid)
|| algid.equals(AlgorithmId.DSA_OIW_oid))
return "DSA";
// Common signature types
if (algid.equals(AlgorithmId.sha1WithEC_oid))
return "SHA1withEC";
if (algid.equals(AlgorithmId.sha256WithEC_oid))
return "SHA256withEC";
if (algid.equals(AlgorithmId.sha384WithEC_oid))
return "SHA384withEC";
if (algid.equals(AlgorithmId.sha512WithEC_oid))
return "SHA512withEC";
if (algid.equals(AlgorithmId.md5WithRSAEncryption_oid))
return "MD5withRSA";
if (algid.equals(AlgorithmId.md2WithRSAEncryption_oid))
return "MD2withRSA";
if (algid.equals(AlgorithmId.sha1WithRSAEncryption_oid))
return "SHA1withRSA";
if (algid.equals(AlgorithmId.sha256WithRSAEncryption_oid))
return "SHA256withRSA";
if (algid.equals(AlgorithmId.sha384WithRSAEncryption_oid))
return "SHA384withRSA";
if (algid.equals(AlgorithmId.sha512WithRSAEncryption_oid))
return "SHA512withRSA";
if (algid.equals(AlgorithmId.sha1WithDSA_oid)
|| algid.equals(AlgorithmId.sha1WithDSA_OIW_oid)
|| algid.equals(AlgorithmId.shaWithDSA_OIW_oid))
return "SHA1withDSA";
// default returns a dot-notation ID
return "OID." + algid.toString();
}
/**
* Returns the ISO OID for this algorithm. This is usually converted
* to a string and used as part of an algorithm name, for example
* "OID.1.3.14.3.2.13" style notation. Use the getName
call when you do not need to ensure cross-system
* portability
* of algorithm names, or need a user friendly name.
* @return the ISO OID
*/
final public ObjectIdentifier getOID() {
return algid;
}
/**
* Returns a name for the algorithm which may be more intelligible
* to humans than the algorithm's OID, but which won't necessarily
* be comprehensible on other systems. For example, this might
* return a name such as "MD5withRSA" for a signature algorithm on
* some systems. It also returns names like "OID.1.2.3.4", when
* no particular name for the algorithm is known.
* @return the name
*/
public String getName() {
return algName();
}
/**
* Returns a string describing only the algorithm without parameters.
*
* Use toStringWithParams() for algorithm name and paramaters, or
* paramsToString() for just parameters.
*
* @return algorithm name
*/
@Override
public String toString() {
return algName();
}
/**
* Returns a string describing the algorithm and its parameters.
* @return algorithm name and parameters
*/
public String toStringWithParams() {
if (params == null) {
return algName();
}
return algName() + " " + paramsToString();
}
/**
* Returns the DER encoded parameter, which can then be
* used to initialize java.security.AlgorithmParamters.
*
* @return DER encoded parameters, or null not present.
* @throws IOException If an error occurred.
*/
public byte[] getEncodedParams() throws IOException {
return params == null ? null : params.toByteArray();
}
/**
* Provides a human-readable description of the algorithm parameters.
* This may be redefined by subclasses which parse those parameters.
* @return algorithm parameters description
*/
protected String paramsToString() {
if (params == null) {
return "";
} else if (algParams != null) {
return algParams.toString();
} else {
return ", params unparsed";
}
}
/**
* Returns true iff the argument indicates the same algorithm
* with the same parameters.
* @param other another algorithm ID
* @return true iff it's identical
*/
public boolean equals(AlgorithmId other) {
if (!algid.equals(other.algid))
return false;
else if (params == null && other.params == null)
return true;
else if (params == null)
return false;
else
return params.equals(other.params);
}
/**
* Compares this AlgorithmID to another. If algorithm parameters are
* available, they are compared. Otherwise, just the object IDs
* for the algorithm are compared.
*
* @param other preferably an AlgorithmId, else an ObjectIdentifier
*/
@Override
public boolean equals(Object other) {
if (other instanceof AlgorithmId)
return equals((AlgorithmId) other);
else if (other instanceof ObjectIdentifier)
return equals((ObjectIdentifier) other);
else
return false;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((algParams == null) ? 0 : algParams.hashCode());
result = prime * result + ((algid == null) ? 0 : algid.hashCode());
result = prime * result + ((params == null) ? 0 : params.hashCode());
result = prime * result + ((paramsString == null) ? 0 : paramsString.hashCode());
return result;
}
/**
* Compares two algorithm IDs for equality. Returns true iff
* they are the same algorithm, ignoring algorithm parameters.
* @param id another algorithm ID
* @return true iff it's the same
*/
public final boolean equals(ObjectIdentifier id) {
return algid.equals(id);
}
public static AlgorithmParameters createPSSAlgorithmParametersFromData(byte[] der) throws Exception {
if (der == null) {
throw new Exception("Invalid input data.");
}
AlgorithmParameters pssParams = null;
try {
pssParams = AlgorithmParameters.getInstance("RSAPSSAlgorithmParameters", "Mozilla-JSS");
} catch (NoSuchProviderException e) {
throw new Exception(e);
}
try {
pssParams.init(der);
} catch (IOException e) {
throw new Exception("Error intializing RSAPSS parameters: " + e);
}
return pssParams;
}
/**
* Used to create the PSS algorithm params needed for RSA PSS signatures.
* @param algName algorithm name
* @return algorithm parameters
* @throws IllegalArgumentException
* @throws NoSuchProviderException
* @throws InvalidParameterSpecException
* @throws NoSuchAlgorithmException
*/
public static AlgorithmParameters createPSSAlgorithmParameters(String algName) throws IllegalArgumentException, NoSuchProviderException, InvalidParameterSpecException, NoSuchAlgorithmException {
if (algName == null) {
throw new IllegalArgumentException("Invalid Algorithm name input.");
}
if (!algName.contains("PSS")) {
throw new IllegalArgumentException("PSS Algorithm name not supported.");
}
AlgorithmParameters pssParams = null;
PSSParameterSpec pssSpec = null;
// Make sure we are in the RSA PSS family
// Only support for now RSAPSS with SHA256 , 384, and 512
// Resulting in different PSSParameterSpec values
if ("SHA256withRSA/PSS".equals(algName)) {
// Support the most often used SHA-256 hash alg version .
pssSpec = new PSSParameterSpec("SHA-256", "MGF1", MGF1ParameterSpec.SHA256, 32, 1);
} else if ("SHA384withRSA/PSS".equals(algName)) {
pssSpec = new PSSParameterSpec("SHA-384", "MGF1", MGF1ParameterSpec.SHA384, 48, 1);
} else if ("SHA512withRSA/PSS".equals(algName)) {
pssSpec = new PSSParameterSpec("SHA-512", "MGF1", MGF1ParameterSpec.SHA512, 64, 1);
} else {
throw new IllegalArgumentException("Unsupported algorithm: " + algName);
}
pssParams = AlgorithmParameters.getInstance("RSAPSSAlgorithmParameters", "Mozilla-JSS");
pssParams.init(pssSpec);
return pssParams;
}
/*****************************************************************/
/*
* HASHING ALGORITHMS
*/
private static final int MD2_data[] = { 1, 2, 840, 113549, 2, 2 };
private static final int MD5_data[] = { 1, 2, 840, 113549, 2, 5 };
// sha = { 1, 3, 14, 3, 2, 18 };
@Deprecated(since="5.0.1", forRemoval=true)
private static final int SHA1_OIW_data[] = { 1, 3, 14, 3, 2, 26 };
private static final int SHA256_data[] = { 2, 16, 840, 1, 101, 3, 4, 2, 1 };
private static final int SHA384_data[] = { 2, 16, 840, 1, 101, 3, 4, 2, 2 };
private static final int SHA512_data[] = { 2, 16, 840, 1, 101, 3, 4, 2, 3 };
private static final int MGF1_data[] = { 1,2,840,113549,1,1,8 };
/**
* Algorithm ID for the MD2 Message Digest Algorthm, from RFC 1319.
* OID = 1.2.840.113549.2.2
*/
public static final ObjectIdentifier MD2_oid = new ObjectIdentifier(MD2_data);
/**
* Algorithm ID for the MD5 Message Digest Algorthm, from RFC 1321.
* OID = 1.2.840.113549.2.5
*/
public static final ObjectIdentifier MD5_oid = new ObjectIdentifier(MD5_data);
/**
* Algorithm ID for the SHA1 Message Digest Algorithm, from FIPS 180-1.
* This is sometimes called "SHA", though that is often confusing since
* many people refer to FIPS 180 (which has an error) as defining SHA.
* OID = 1.3.14.3.2.26
*/
@Deprecated(since="5.0.1", forRemoval=true)
public static final ObjectIdentifier SHA_oid = new ObjectIdentifier(SHA1_OIW_data);
public static final ObjectIdentifier SHA256_oid = new ObjectIdentifier(SHA256_data);
public static final ObjectIdentifier SHA384_oid = new ObjectIdentifier(SHA384_data);
public static final ObjectIdentifier SHA512_oid = new ObjectIdentifier(SHA512_data);
public static final ObjectIdentifier MGF1_oid = new ObjectIdentifier(MGF1_data);
/*
* COMMON PUBLIC KEY TYPES
*/
private static final int DH_data[] = { 1, 2, 840, 113549, 1, 3, 1 };
private static final int DH_PKIX_data[] = { 1, 2, 840, 10046, 2, 1 };
private static final int DSA_OIW_data[] = { 1, 3, 14, 3, 2, 12 };
private static final int DSA_PKIX_data[] = { 1, 2, 840, 10040, 4, 1 };
private static final int RSA_data[] = { 1, 2, 5, 8, 1, 1 };
private static final int RSAEncryption_data[] =
{ 1, 2, 840, 113549, 1, 1, 1 };
private static final int ANSI_X962_public_key_data[] =
{ 1, 2, 840, 10045, 2, 1 };
private static final int ANSI_X962_sha1_with_ec_data[] =
{ 1, 2, 840, 10045, 4, 1 };
public static final ObjectIdentifier ANSIX962_EC_Public_Key_oid = new ObjectIdentifier(ANSI_X962_public_key_data);
@Deprecated(since="5.0.1", forRemoval=true)
public static final ObjectIdentifier ANSIX962_SHA1_With_EC_oid = new ObjectIdentifier(ANSI_X962_sha1_with_ec_data);
/*
* Note the preferred OIDs are named simply with no "OIW" or
* "PKIX" in them, even though they may point to data from these
* specs; e.g. SHA_oid, DH_oid, DSA_oid, SHA1WithDSA_oid...
*/
/**
* Algorithm ID for Diffie Hellman Key agreement, from PKCS #3.
* Parameters include public values P and G, and may optionally specify
* the length of the private key X. Alternatively, algorithm parameters
* may be derived from another source such as a Certificate Authority's
* certificate.
* OID = 1.2.840.113549.1.3.1
*/
public static final ObjectIdentifier DH_oid = new ObjectIdentifier(DH_data);
/**
* Algorithm ID for the Diffie Hellman Key Agreement (DH), from the
* IETF PKIX IPKI Part I.
* Parameters may include public values P and G.
* OID = 1.2.840.10046.2.1
*/
public static final ObjectIdentifier DH_PKIX_oid = new ObjectIdentifier(DH_PKIX_data);
/**
* Algorithm ID for the Digital Signing Algorithm (DSA), from the
* NIST OIW Stable Agreements part 12.
* Parameters may include public values P, Q, and G; or these may be
* derived from
* another source such as a Certificate Authority's certificate.
* OID = 1.3.14.3.2.12
*/
public static final ObjectIdentifier DSA_OIW_oid = new ObjectIdentifier(DSA_OIW_data);
/**
* Algorithm ID for the Digital Signing Algorithm (DSA), from the
* IETF PKIX IPKI Part I.
* Parameters may include public values P, Q, and G; or these may be
* derived from
* another source such as a Certificate Authority's certificate.
* OID = 1.2.840.10040.4.1
*/
public static final ObjectIdentifier DSA_oid = new ObjectIdentifier(DSA_PKIX_data);
/**
* Algorithm ID for RSA keys used for any purpose, as defined in X.509.
* The algorithm parameter is a single value, the number of bits in the
* public modulus.
* OID = 1.2.5.8.1.1
*/
public static final ObjectIdentifier RSA_oid = new ObjectIdentifier(RSA_data);
/**
* Algorithm ID for RSA keys used with RSA encryption, as defined
* in PKCS #1. There are no parameters associated with this algorithm.
* OID = 1.2.840.113549.1.1.1
*/
public static final ObjectIdentifier RSAEncryption_oid = new ObjectIdentifier(RSAEncryption_data);
/*
* COMMON SIGNATURE ALGORITHMS
*/
@Deprecated(since="5.0.1", forRemoval=true)
private static final int sha1WithEC_data[] =
{ 1, 2, 840, 10045, 4, 1 };
private static final int sha224WithEC_data[] =
{ 1, 2, 840, 10045, 4, 3, 1 };
private static final int sha256WithEC_data[] =
{ 1, 2, 840, 10045, 4, 3, 2 };
private static final int sha384WithEC_data[] =
{ 1, 2, 840, 10045, 4, 3, 3 };
private static final int sha512WithEC_data[] =
{ 1, 2, 840, 10045, 4, 3, 4 };
private static final int md2WithRSAEncryption_data[] =
{ 1, 2, 840, 113549, 1, 1, 2 };
private static final int md5WithRSAEncryption_data[] =
{ 1, 2, 840, 113549, 1, 1, 4 };
@Deprecated(since="5.0.1", forRemoval=true)
private static final int sha1WithRSAEncryption_data[] =
{ 1, 2, 840, 113549, 1, 1, 5 };
private static final int sha256WithRSAEncryption_data[] =
{ 1, 2, 840, 113549, 1, 1, 11 };
private static final int sha384WithRSAEncryption_data[] =
{ 1, 2, 840, 113549, 1, 1, 12 };
private static final int sha512WithRSAEncryption_data[] =
{ 1, 2, 840, 113549, 1, 1, 13 };
@Deprecated(since="5.0.1", forRemoval=true)
private static final int sha1WithRSAEncryption_OIW_data[] =
{ 1, 3, 14, 3, 2, 29 };
@Deprecated(since="5.0.1", forRemoval=true)
private static final int shaWithDSA_OIW_data[] =
{ 1, 3, 14, 3, 2, 13 };
@Deprecated(since="5.0.1", forRemoval=true)
private static final int sha1WithDSA_OIW_data[] =
{ 1, 3, 14, 3, 2, 27 };
@Deprecated(since="5.0.1", forRemoval=true)
private static final int dsaWithSHA1_PKIX_data[] =
{ 1, 2, 840, 10040, 4, 3 };
private static final int rsaPSS_data[] =
{ 1, 2, 840, 113549, 1, 1, 10 };
@Deprecated(since="5.0.1", forRemoval=true)
public static final ObjectIdentifier sha1WithEC_oid = new
ObjectIdentifier(sha1WithEC_data);
public static final ObjectIdentifier sha224WithEC_oid = new
ObjectIdentifier(sha224WithEC_data);
public static final ObjectIdentifier sha256WithEC_oid = new
ObjectIdentifier(sha256WithEC_data);
public static final ObjectIdentifier sha384WithEC_oid = new
ObjectIdentifier(sha384WithEC_data);
public static final ObjectIdentifier sha512WithEC_oid = new
ObjectIdentifier(sha512WithEC_data);
public static final ObjectIdentifier rsaPSS_oid = new
ObjectIdentifier(rsaPSS_data);
/**
* Identifies a signing algorithm where an MD2 digest is encrypted
* using an RSA private key; defined in PKCS #1. Use of this
* signing algorithm is discouraged due to MD2 vulnerabilities.
* OID = 1.2.840.113549.1.1.2
*/
public static final ObjectIdentifier md2WithRSAEncryption_oid = new
ObjectIdentifier(md2WithRSAEncryption_data);
/**
* Identifies a signing algorithm where an MD5 digest is
* encrypted using an RSA private key; defined in PKCS #1.
* OID = 1.2.840.113549.1.1.4
*/
public static final ObjectIdentifier md5WithRSAEncryption_oid = new
ObjectIdentifier(md5WithRSAEncryption_data);
/**
* The proper one for sha1/rsa
*/
@Deprecated(since="5.0.1", forRemoval=true)
public static final ObjectIdentifier sha1WithRSAEncryption_oid = new
ObjectIdentifier(sha1WithRSAEncryption_data);
/**
* The proper one for sha256/rsa
*/
public static final ObjectIdentifier sha256WithRSAEncryption_oid = new
ObjectIdentifier(sha256WithRSAEncryption_data);
/**
* The proper one for sha384/rsa
*/
public static final ObjectIdentifier sha384WithRSAEncryption_oid = new
ObjectIdentifier(sha384WithRSAEncryption_data);
/**
* The proper one for sha512/rsa
*/
public static final ObjectIdentifier sha512WithRSAEncryption_oid = new
ObjectIdentifier(sha512WithRSAEncryption_data);
/**
* Identifies a signing algorithm where an SHA1 digest is
* encrypted using an RSA private key; defined in NIST OIW.
* OID = 1.3.14.3.2.29
*/
@Deprecated(since="5.0.1", forRemoval=true)
public static final ObjectIdentifier sha1WithRSAEncryption_OIW_oid = new
ObjectIdentifier(sha1WithRSAEncryption_OIW_data);
/**
* Identifies the FIPS 186 "Digital Signature Standard" (DSS), where a
* SHA digest is signed using the Digital Signing Algorithm (DSA).
* This should not be used.
* OID = 1.3.14.3.2.13
*/
@Deprecated(since="5.0.1", forRemoval=true)
public static final ObjectIdentifier shaWithDSA_OIW_oid = new ObjectIdentifier(shaWithDSA_OIW_data);
/**
* Identifies the FIPS 186 "Digital Signature Standard" (DSS), where a
* SHA1 digest is signed using the Digital Signing Algorithm (DSA).
* OID = 1.3.14.3.2.27
*/
@Deprecated(since="5.0.1", forRemoval=true)
public static final ObjectIdentifier sha1WithDSA_OIW_oid = new ObjectIdentifier(sha1WithDSA_OIW_data);
/**
* Identifies the FIPS 186 "Digital Signature Standard" (DSS), where a
* SHA1 digest is signed using the Digital Signing Algorithm (DSA).
* OID = 1.2.840.10040.4.3
*/
@Deprecated(since="5.0.1", forRemoval=true)
public static final ObjectIdentifier sha1WithDSA_oid = new ObjectIdentifier(dsaWithSHA1_PKIX_data);
/**
* Supported signing algorithms for a DSA key.
*/
@Deprecated(since="5.0.1", forRemoval=true)
public static final String[] DSA_SIGNING_ALGORITHMS = new String[]
{ "SHA1withDSA" };
/**
* Supported signing algorithms for a RSA key.
*/
public static final String[] RSA_SIGNING_ALGORITHMS = new String[]
{ "SHA256withRSA", "SHA384withRSA", "SHA512withRSA", "SHA1withRSA", "SHA256withRSA/PSS", "SHA384withRSA/PSS", "SHA512withRSA/PSS" };
public static final String[] EC_SIGNING_ALGORITHMS = new String[]
{ "SHA256withEC", "SHA384withEC", "SHA512withEC", "SHA1withEC" };
/**
* All supported signing algorithms.
*/
public static final String[] ALL_SIGNING_ALGORITHMS = ArrayUtils.addAll(RSA_SIGNING_ALGORITHMS, EC_SIGNING_ALGORITHMS);
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509/Attribute.java 0000664 0000000 0000000 00000024600 14565430767 0027732 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.x509;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.Enumeration;
import java.util.Vector;
import org.mozilla.jss.netscape.security.util.DerEncoder;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
import org.mozilla.jss.netscape.security.util.ObjectIdentifier;
/**
* An attribute, as identified by some attribute ID, has some particular values.
* Values are as a rule ASN.1 printable strings. A conventional set of type IDs
* is recognized when parsing. The following shows the syntax:
*
*
*
* Attribute ::= SEQUENCE {
* type AttributeType,
* value SET OF AttributeValue
* -- at least one value is required --}
*
* AttributeType ::= OBJECT IDENTIFIER
*
* AttributeValue ::= ANY
*
*
*
* Refer to draft-ietf-pkix-ipki-part1-11 for the support attributes listed on
* page 96 of the internet draft. The are listed here for easy reference: name,
* common name, surname, given name, initials, generation qualifier, dn qualifier,
* country name, locality name, state or province name, organization name, organization
* unit name, title, pkcs9 email. Not all the attributes are supported. Please check
* the X500NameAttrMap for defined attributes.
*
* @author Christine Ho
*/
public final class Attribute implements Serializable, DerEncoder {
/**
*
*/
private static final long serialVersionUID = -931486084625476764L;
//private variables
ObjectIdentifier oid;
Vector valueSet = new Vector<>();
transient protected X500NameAttrMap attrMap;
//========== CONSTRUCTOR ==================================
/**
* Construct an attribute from attribute type and attribute value
*
* @param oid the object identifier of the attribute type
* @param value the value string
*/
public Attribute(ObjectIdentifier oid, String value)
throws IOException {
//pre-condition verification
if ((oid == null) || (value == null))
throw new IOException("Invalid Input - null passed");
attrMap = X500NameAttrMap.getDefault();
this.oid = oid;
valueSet.addElement(value);
}
/**
* Construct an attribute from attribute type and attribute values
*
* @param oid the object identifier of the attribute type
* @param values String value vector
*/
public Attribute(ObjectIdentifier oid, Vector values)
throws IOException {
//pre-condition verification
if ((oid == null) || (values == null))
throw new IOException("Invalid Input - null passed");
attrMap = X500NameAttrMap.getDefault();
this.oid = oid;
//copy the value into the valueSet list
Enumeration vals = values.elements();
while (vals.hasMoreElements()) {
valueSet.addElement(vals.nextElement());
}
}
/**
* Construct an attribute from attribute type and attribute values
*
* @param attr oid attribute type string CN,OU,O,C,L,TITLE,ST,STREET,UID,MAIL,E,DC
* @param values String value vector
*/
public Attribute(String attr, Vector values)
throws IOException {
//pre-condition verification
if ((attr == null) || (values == null))
throw new IOException("Invalid Input - null passed");
ObjectIdentifier identifier = null;
try {
identifier = new ObjectIdentifier(attr);
} catch (Exception e) {
}
ObjectIdentifier id = identifier;
if (identifier == null) {
attrMap = X500NameAttrMap.getDefault();
id = attrMap.getOid(attr);
if (id == null)
throw new IOException("Attr is not supported - does not contain in attr map");
}
this.oid = id;
//copy the value into the valueSet list
Enumeration vals = values.elements();
while (vals.hasMoreElements()) {
valueSet.addElement(vals.nextElement());
}
}
/**
* Construct an attribute from a der encoded object. This der
* der encoded value should represent the attribute object.
*
* @param val the attribute object in der encode form.
*/
public Attribute(DerValue val)
throws IOException {
//pre-condition verification
if (val == null)
throw new IOException("Invalid Input - null passed");
attrMap = X500NameAttrMap.getDefault();
decodeThis(val);
}
//========== PUBLIC METHODS ==================================
/**
* Returns the OID in the Attribute.
*
* @return the ObjectIdentifier in this Attribute.
*/
public ObjectIdentifier getOid() {
return oid;
}
/**
* Returns enumeration of values in this attribute.
*
* @return Enumeration of values of this Attribute.
*/
public Enumeration getValues() {
if (valueSet == null)
return null;
return valueSet.elements();
}
/**
* Encodes the Attribute to a Der output stream.
* Attribute are encoded as a SEQUENCE of two elements.
*
* @param out The Der output stream.
*/
public void encode(DerOutputStream out) throws IOException {
encodeThis(out);
}
/**
* DER encode this object onto an output stream.
* Implements the DerEncoder
interface.
*
* @param out
* the output stream on which to write the DER encoding.
*
* @exception IOException on encoding error.
*/
@Override
public void derEncode(OutputStream out) throws IOException {
encodeThis(out);
}
/**
* Prints a string version of this extension.
*/
@Override
public String toString() {
String theoid = "Attribute: " + oid + "\n";
StringBuffer values = new StringBuffer("Values: ");
Enumeration n = valueSet.elements();
if (n.hasMoreElements()) {
values.append(n.nextElement());
while (n.hasMoreElements())
values.append("," + n.nextElement());
}
return theoid + values.toString() + "\n";
}
//========== PRIVATE METHODS ==================================
//encode the attribute object
private void encodeThis(OutputStream out)
throws IOException {
try (DerOutputStream tmp2 = new DerOutputStream()) {
DerOutputStream tmp = new DerOutputStream();
tmp.putOID(oid);
encodeValueSet(tmp);
tmp2.write(DerValue.tag_Sequence, tmp);
out.write(tmp2.toByteArray());
}
}
//encode the attribute object
private void encodeValueSet(OutputStream out)
throws IOException {
try (DerOutputStream tmp2 = new DerOutputStream()) {
DerOutputStream tmp = new DerOutputStream();
//get the attribute converter
AVAValueConverter converter = attrMap.getValueConverter(oid);
if (converter == null) {
converter = new GenericValueConverter();
//throw new IOException("Converter not found: unsupported attribute type");
}
//loop through all the values and encode
Enumeration vals = valueSet.elements();
while (vals.hasMoreElements()) {
String val = vals.nextElement();
DerValue derobj = converter.getValue(val);
derobj.encode(tmp);
}
tmp2.write(DerValue.tag_SetOf, tmp);
out.write(tmp2.toByteArray());
}
}
//decode the attribute object
private void decodeThis(DerValue val)
throws IOException {
//pre-condition verification
if (val == null) {
throw new IOException("Invalid Input - null passed.");
}
if (val.tag != DerValue.tag_Sequence) {
throw new IOException("Invalid encoding for Attribute.");
}
if (val.data.available() == 0) {
throw new IOException("No data available in "
+ "passed DER encoded value.");
}
this.oid = val.data.getDerValue().getOID();
if (val.data.available() == 0) {
throw new IOException("Invalid encoding for Attribute - value missing");
}
decodeValueSet(val.data.getDerValue());
if (this.oid == null)
throw new IOException("Invalid encoding for Attribute - OID missing");
}
//decode the attribute value set
private void decodeValueSet(DerValue val)
throws IOException {
//pre-condition verification
if (val == null) {
throw new IOException("Invalid Input - null passed.");
}
AVAValueConverter converter = attrMap.getValueConverter(this.oid);
if (converter == null) {
converter = new GenericValueConverter();
//throw new IOException("Attribute is not supported - not in attr map");
}
if (val.tag != DerValue.tag_SetOf) {
throw new IOException("Invalid encoding for Attribute Value Set.");
}
if (val.data.available() == 0) {
throw new IOException("No data available in "
+ "passed DER encoded attribute value set.");
}
//get the value set
while (val.data.available() != 0) {
DerValue value = val.data.getDerValue();
valueSet.addElement(converter.getAsString(value));
}
}
}
AuthorityKeyIdentifierExtension.java 0000664 0000000 0000000 00000030027 14565430767 0034251 0 ustar 00root root 0000000 0000000 jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.x509;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Array;
import java.util.Enumeration;
import java.util.Vector;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
/**
* This class represents the Authority Key Identifier Extension.
*
*
* The authority key identifier extension provides a means of identifying the particular public key used to sign a
* certificate. This extension would be used where an issuer has multiple signing keys (either due to multiple
* concurrent key pairs or due to changeover).
*
* The ASN.1 syntax for this is:
*
*
* AuthorityKeyIdentifier ::= SEQUENCE {
* keyIdentifier [0] KeyIdentifier OPTIONAL,
* authorityCertIssuer [1] GeneralNames OPTIONAL,
* authorityCertSerialNumber [2] CertificateSerialNumber OPTIONAL
* }
* KeyIdentifier ::= OCTET STRING
*
*
* @author Amit Kapoor
* @author Hemma Prafullchandra
* @version 1.9
* @see Extension
* @see CertAttrSet
*/
public class AuthorityKeyIdentifierExtension extends Extension
implements CertAttrSet {
/**
*
*/
private static final long serialVersionUID = -157913621972354170L;
/**
* Identifier for this attribute, to be used with the
* get, set, delete methods of Certificate, x509 type.
*/
public static final String IDENT =
"x509.info.extensions.AuthorityKeyIdentifier";
/**
* Attribute names.
*/
public static final String NAME = "AuthorityKeyIdentifier";
public static final String KEY_ID = "key_id";
public static final String AUTH_NAME = "auth_name";
public static final String SERIAL_NUMBER = "serial_number";
// Private data members
private static final byte TAG_ID = 0;
private static final byte TAG_NAMES = 1;
private static final byte TAG_SERIAL_NUM = 2;
private KeyIdentifier id = null;
private GeneralNames names = null;
private SerialNumber serialNum = null;
// Encode only the extension value
private void encodeThis() throws IOException {
try (DerOutputStream tmp = new DerOutputStream();
DerOutputStream seq = new DerOutputStream()) {
if (id != null) {
DerOutputStream tmp1 = new DerOutputStream();
id.encode(tmp1);
tmp.writeImplicit(DerValue.createTag(DerValue.TAG_CONTEXT,
false, TAG_ID), tmp1);
}
try {
if (names != null) {
DerOutputStream tmp1 = new DerOutputStream();
names.encode(tmp1);
tmp.writeImplicit(DerValue.createTag(DerValue.TAG_CONTEXT,
true, TAG_NAMES), tmp1);
}
} catch (Exception e) {
throw new IOException(e);
}
if (serialNum != null) {
DerOutputStream tmp1 = new DerOutputStream();
serialNum.encode(tmp1);
tmp.writeImplicit(DerValue.createTag(DerValue.TAG_CONTEXT,
false, TAG_SERIAL_NUM), tmp1);
}
seq.write(DerValue.tag_Sequence, tmp);
this.extensionValue = seq.toByteArray();
}
}
/**
* Exposed critical parameter. 99/11/03
*/
public AuthorityKeyIdentifierExtension(boolean critical,
KeyIdentifier kid, GeneralNames name,
SerialNumber sn)
throws IOException {
this.id = kid;
this.names = name;
this.serialNum = sn;
this.extensionId = PKIXExtensions.AuthorityKey_Id;
this.critical = critical;
encodeThis();
}
/**
* The default constructor for this extension. Null parameters make
* the element optional (not present).
*
* @param kid the KeyIdentifier associated with this extension.
* @param name the GeneralNames associated with this extension
* @param sn the CertificateSerialNumber associated with
* this extension.
* @exception IOException on error.
*/
public AuthorityKeyIdentifierExtension(KeyIdentifier kid, GeneralNames name,
SerialNumber sn)
throws IOException {
this.id = kid;
this.names = name;
this.serialNum = sn;
this.extensionId = PKIXExtensions.AuthorityKey_Id;
this.critical = false;
encodeThis();
}
/**
* Create the extension from the passed DER encoded value of the same.
*
* @param critical true if the extension is to be treated as critical.
* @param value Array of DER encoded bytes of the actual value.
* @exception IOException on error.
*/
public AuthorityKeyIdentifierExtension(Boolean critical, Object value)
throws IOException {
this.extensionId = PKIXExtensions.AuthorityKey_Id;
this.critical = critical.booleanValue();
if (!(value instanceof byte[]))
throw new IOException("Illegal argument type");
int len = Array.getLength(value);
byte[] extValue = new byte[len];
System.arraycopy(value, 0, extValue, 0, len);
this.extensionValue = extValue;
DerValue val = new DerValue(extValue);
if (val.tag != DerValue.tag_Sequence) {
throw new IOException("Invalid encoding for " +
"AuthorityKeyIdentifierExtension.");
}
// NB. this is always encoded with the IMPLICIT tag
// The checks only make sense if we assume implicit tagging,
// with explicit tagging the form is always constructed.
while (val.data.available() != 0) {
DerValue opt = val.data.getDerValue();
if (opt.isContextSpecific(TAG_ID) && !opt.isConstructed()) {
if (id != null)
throw new IOException("Duplicate KeyIdentifier in " +
"AuthorityKeyIdentifier.");
opt.resetTag(DerValue.tag_OctetString);
id = new KeyIdentifier(opt);
} else if (opt.isContextSpecific(TAG_NAMES) &&
opt.isConstructed()) {
if (names != null)
throw new IOException("Duplicate GeneralNames in " +
"AuthorityKeyIdentifier.");
try {
opt.resetTag(DerValue.tag_Sequence);
names = new GeneralNames(opt);
} catch (GeneralNamesException e) {
throw new IOException(e);
}
} else if (opt.isContextSpecific(TAG_SERIAL_NUM) &&
!opt.isConstructed()) {
if (serialNum != null)
throw new IOException("Duplicate SerialNumber in " +
"AuthorityKeyIdentifier.");
opt.resetTag(DerValue.tag_Integer);
serialNum = new SerialNumber(opt);
} else
throw new IOException("Invalid encoding of " +
"AuthorityKeyIdentifierExtension.");
}
}
/**
* Return the object as a string.
*/
@Override
public String toString() {
String s = super.toString() + "AuthorityKeyIdentifier [\n";
if (id != null) {
s += id.toString();
}
if (names != null) {
s += names.toString() + "\n";
}
if (serialNum != null) {
s += serialNum.toString() + "\n";
}
return (s + "]\n");
}
/**
* Decode the extension from the InputStream.
*
* @param in the InputStream to unmarshal the contents from.
* @exception IOException on decoding or validity errors.
*/
@Override
public void decode(InputStream in) throws IOException {
throw new IOException("Method not to be called directly.");
}
/**
* Write the extension to the OutputStream.
*
* @param out the OutputStream to write the extension to.
* @exception IOException on error.
*/
@Override
public void encode(OutputStream out) throws IOException {
DerOutputStream tmp = new DerOutputStream();
if (this.extensionValue == null) {
extensionId = PKIXExtensions.AuthorityKey_Id;
critical = false;
encodeThis();
}
super.encode(tmp);
out.write(tmp.toByteArray());
}
/**
* Set the attribute value.
*/
@Override
public void set(String name, Object obj) throws IOException {
clearValue();
if (name.equalsIgnoreCase(KEY_ID)) {
if (!(obj instanceof KeyIdentifier)) {
throw new IOException("Attribute value should be of " +
"type KeyIdentifier.");
}
id = (KeyIdentifier) obj;
} else if (name.equalsIgnoreCase(AUTH_NAME)) {
if (!(obj instanceof GeneralNames)) {
throw new IOException("Attribute value should be of " +
"type GeneralNames.");
}
names = (GeneralNames) obj;
} else if (name.equalsIgnoreCase(SERIAL_NUMBER)) {
if (!(obj instanceof SerialNumber)) {
throw new IOException("Attribute value should be of " +
"type SerialNumber.");
}
serialNum = (SerialNumber) obj;
} else {
throw new IOException("Attribute name not recognized by " +
"CertAttrSet:AuthorityKeyIdentifier.");
}
}
/**
* Get the attribute value.
*/
@Override
public Object get(String name) throws IOException {
if (name.equalsIgnoreCase(KEY_ID)) {
return (id);
} else if (name.equalsIgnoreCase(AUTH_NAME)) {
return (names);
} else if (name.equalsIgnoreCase(SERIAL_NUMBER)) {
return (serialNum);
} else {
throw new IOException("Attribute name not recognized by " +
"CertAttrSet:AuthorityKeyIdentifier.");
}
}
/**
* Delete the attribute value.
*/
@Override
public void delete(String name) throws IOException {
if (name.equalsIgnoreCase(KEY_ID)) {
id = null;
} else if (name.equalsIgnoreCase(AUTH_NAME)) {
names = null;
} else if (name.equalsIgnoreCase(SERIAL_NUMBER)) {
serialNum = null;
} else {
throw new IOException("Attribute name not recognized by " +
"CertAttrSet:AuthorityKeyIdentifier.");
}
}
/**
* Return an enumeration of names of attributes existing within this
* attribute.
*/
@Override
public Enumeration getAttributeNames() {
Vector elements = new Vector<>();
elements.addElement(KEY_ID);
elements.addElement(AUTH_NAME);
elements.addElement(SERIAL_NUMBER);
return (elements.elements());
}
/**
* Return the name of this attribute.
*/
@Override
public String getName() {
return (NAME);
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509/BasicConstraintsExtension.java 0000664 0000000 0000000 00000023021 14565430767 0033131 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.x509;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Array;
import java.util.Enumeration;
import java.util.Vector;
import org.mozilla.jss.netscape.security.util.BigInt;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
/**
* This class represents the Basic Constraints Extension.
*
*
* The basic constraints extension identifies whether the subject of the certificate is a CA and how deep a
* certification path may exist through that CA.
*
*
* The ASN.1 syntax for this extension is:
* BasicConstraints ::= SEQUENCE {
* cA BOOLEAN DEFAULT FALSE,
* pathLenConstraint INTEGER (0..MAX) OPTIONAL
* }
*
*
* @author Amit Kapoor
* @author Hemma Prafullchandra
* @version 1.7
* @see CertAttrSet
* @see Extension
*/
public class BasicConstraintsExtension extends Extension
implements CertAttrSet {
/**
*
*/
private static final long serialVersionUID = 6213957094939885889L;
/**
* Identifier for this attribute, to be used with the
* get, set, delete methods of Certificate, x509 type.
*/
public static final String IDENT = "x509.info.extensions.BasicConstraints";
/**
* Attribute names.
*/
public static final String NAME = "BasicConstraints";
public static final String IS_CA = "is_ca";
public static final String PATH_LEN = "path_len";
// Private data members
private boolean ca = false;
private int pathLen = -1;
// Encode this extension value
private void encodeThis() throws IOException {
try (DerOutputStream out = new DerOutputStream()) {
DerOutputStream tmp = new DerOutputStream();
if (ca) {
tmp.putBoolean(ca);
}
if (pathLen >= 0) {
tmp.putInteger(new BigInt(pathLen));
}
out.write(DerValue.tag_Sequence, tmp);
this.extensionValue = out.toByteArray();
}
}
/**
* Default constructor for this object.
*
* @param ca true, if the subject of the Certificate is a CA.
* @param len specifies the depth of the certification path.
*/
public BasicConstraintsExtension(boolean ca, int len) throws IOException {
this.ca = ca;
this.pathLen = len;
this.extensionId = PKIXExtensions.BasicConstraints_Id;
if (ca) {
critical = true;
} else {
critical = false;
}
encodeThis();
}
/**
* Default constructor for this object.
*
* @param ca true, if the subject of the Certificate is a CA.
* @param len specifies the depth of the certification path.
*/
public BasicConstraintsExtension(boolean ca, boolean critical, int len) throws IOException {
this.ca = ca;
this.pathLen = len;
this.extensionId = PKIXExtensions.BasicConstraints_Id;
this.critical = critical;
encodeThis();
}
/**
* Create the extension from the passed DER encoded value of the same.
*
* @param value the DER encoded value of the extension.
* @exception IOException on error.
*/
public BasicConstraintsExtension(Boolean critical, Object value)
throws IOException {
this.extensionId = PKIXExtensions.BasicConstraints_Id;
this.critical = critical.booleanValue();
if (value instanceof byte[]) {
int len = Array.getLength(value);
byte[] extValue = new byte[len];
System.arraycopy(value, 0, extValue, 0, len);
this.extensionValue = extValue;
DerValue val = new DerValue(extValue);
if (val.tag != DerValue.tag_Sequence) {
throw new IOException("Invalid encoding of BasicConstraints");
}
// non-CA cert with no limit to certification path length
if (val.data == null || val.data.available() < 1) {
this.ca = false;
this.pathLen = -1;
return;
}
DerValue opt = val.data.getDerValue();
if (opt.tag != DerValue.tag_Boolean) {
this.ca = false;
} else {
this.ca = true;
if (val.data.available() != 0) {
opt = val.data.getDerValue();
} else {
this.pathLen = -1;
return;
}
}
if (opt.tag != DerValue.tag_Integer) {
throw new IOException("Invalid encoding of BasicConstraints");
}
this.pathLen = (opt.getInteger()).toInt();
/*
* Activate this check once again after PKIX profiling
* is a standard and this check no longer imposes an
* interoperability barrier.
* if (ca) {
* if (!this.critical) {
* throw new IOException("Criticality cannot be false for CA.");
* }
* }
*/
} else
throw new IOException("Invalid argument type");
}
/**
* Return user readable form of extension.
*/
@Override
public String toString() {
String s = super.toString() + "BasicConstraints:[\n";
s += ((ca) ? ("CA:true") : ("CA:false")) + "\n";
if (pathLen >= 0) {
s += "PathLen:" + pathLen + "\n";
} else {
s += "PathLen: undefined\n";
}
return (s + "]\n");
}
/**
* Decode the extension from the InputStream.
*
* @param in the InputStream to unmarshal the contents from.
* @exception IOException on decoding or validity errors.
*/
@Override
public void decode(InputStream in) throws IOException {
throw new IOException("Method not to be called directly.");
}
/**
* Encode this extension value to the output stream.
*
* @param out the DerOutputStream to encode the extension to.
*/
@Override
public void encode(OutputStream out) throws IOException {
DerOutputStream tmp = new DerOutputStream();
if (extensionValue == null) {
this.extensionId = PKIXExtensions.BasicConstraints_Id;
/* #57286 - so that profile can set critiality */
/*
if (ca) {
critical = true;
} else {
critical = false;
}
*/
encodeThis();
}
super.encode(tmp);
out.write(tmp.toByteArray());
}
/**
* Set the attribute value.
*/
@Override
public void set(String name, Object obj) throws IOException {
clearValue();
if (name.equalsIgnoreCase(IS_CA)) {
if (!(obj instanceof Boolean)) {
throw new IOException("Attribute value should be of type Boolean.");
}
ca = ((Boolean) obj).booleanValue();
} else if (name.equalsIgnoreCase(PATH_LEN)) {
if (!(obj instanceof Integer)) {
throw new IOException("Attribute value should be of type Integer.");
}
pathLen = ((Integer) obj).intValue();
} else {
throw new IOException("Attribute name not recognized by " +
"CertAttrSet:BasicConstraints.");
}
}
/**
* Get the attribute value.
*/
@Override
public Object get(String name) throws IOException {
if (name.equalsIgnoreCase(IS_CA)) {
return (Boolean.valueOf(ca));
} else if (name.equalsIgnoreCase(PATH_LEN)) {
return (Integer.valueOf(pathLen));
} else {
throw new IOException("Attribute name not recognized by " +
"CertAttrSet:BasicConstraints.");
}
}
/**
* Delete the attribute value.
*/
@Override
public void delete(String name) throws IOException {
if (name.equalsIgnoreCase(IS_CA)) {
ca = false;
} else if (name.equalsIgnoreCase(PATH_LEN)) {
pathLen = -1;
} else {
throw new IOException("Attribute name not recognized by " +
"CertAttrSet:BasicConstraints.");
}
}
/**
* Return an enumeration of names of attributes existing within this
* attribute.
*/
@Override
public Enumeration getAttributeNames() {
Vector elements = new Vector<>();
elements.addElement(IS_CA);
elements.addElement(PATH_LEN);
return (elements.elements());
}
/**
* Return the name of this attribute.
*/
@Override
public String getName() {
return (NAME);
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509/CIDRNetmask.java 0000664 0000000 0000000 00000004563 14565430767 0030041 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2018 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.x509;
import java.nio.ByteBuffer;
/**
* Netmask that is the number of significant bits.
*/
public class CIDRNetmask {
private int n;
public CIDRNetmask(String s) {
this(Integer.parseInt(s));
}
public CIDRNetmask(int n) {
if (n < 0)
throw new InvalidNetmaskException("cannot be negative");
this.n = n;
}
/**
* Write the netmask into a byte buffer.
*
* Throw InvalidNetmaskException if negative or if the
* size exceeds the size of the address type inferred
* from the remaining buffer space (which must be 4
* bytes for IPv4 and 16 bytes for IPv6).
*
* exceeds the size of the buffer
*/
protected void write(ByteBuffer buf) {
// determine type of addr based on bytes left in buffer
int remaining = buf.remaining();
int bits = 0;
if (remaining == 4)
bits = 32;
else if (remaining == 16)
bits = 128;
else
throw new InvalidNetmaskException(
"cannot determine type of address for netmask");
if (n > bits)
throw new InvalidNetmaskException("netmask exceed address size");
int maskSigBits = n;
for (; remaining > 0; remaining--) {
int maskByteSigBits = Math.min(8, maskSigBits);
byte maskByte = (byte) (0xff - (0xff >> maskByteSigBits));
buf.put(maskByte);
maskSigBits = Math.max(maskSigBits - 8, 0);
}
}
@Override
public String toString() {
return "/" + n;
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509/CPSuri.java 0000664 0000000 0000000 00000003342 14565430767 0027134 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.x509;
import java.io.IOException;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
/**
* Represent the CPSuri Qualifier.
*
* CPSuri ::= IA5String;
*
* @author Thomas Kwan
*/
public class CPSuri extends Qualifier {
/**
*
*/
private static final long serialVersionUID = -2814961293159006960L;
private String mURI = null;
public CPSuri(String uri) {
mURI = uri;
}
public CPSuri(DerValue val) throws IOException {
mURI = val.getIA5String();
}
/**
* Write the PolicyQualifier to the DerOutputStream.
*
* @param out the DerOutputStream to write the object to.
* @exception IOException on errors.
*/
@Override
public void encode(DerOutputStream out) throws IOException {
out.putIA5String(mURI);
}
public String getURI() {
return mURI;
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509/CRLDistributionPoint.java 0000664 0000000 0000000 00000042042 14565430767 0032021 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.x509;
import java.io.ByteArrayOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import org.mozilla.jss.asn1.ANY;
import org.mozilla.jss.asn1.ASN1Template;
import org.mozilla.jss.asn1.ASN1Util;
import org.mozilla.jss.asn1.ASN1Value;
import org.mozilla.jss.asn1.BIT_STRING;
import org.mozilla.jss.asn1.EXPLICIT;
import org.mozilla.jss.asn1.InvalidBERException;
import org.mozilla.jss.asn1.SEQUENCE;
import org.mozilla.jss.asn1.Tag;
import org.mozilla.jss.netscape.security.util.BitArray;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
/**
*
* DistributionPoint ::= SEQUENCE {
* distributionPoint [0] DistributionPointName OPTIONAL,
* reasons [1] ReasonFlags OPTIONAL,
* cRLIssuer [2] GeneralNames OPTIONAL }
*
* DistributionPointName ::= CHOICE {
* fullName [0] GeneralNames,
* nameRelativeToCRLIssuer [1] RelativeDistinguishedName }
*
* ReasonFlags ::= BIT STRING {
* unused (0),
* keyCompromise (1),
* cACompromise (2),
* affiliationChanged (3),
* superseded (4),
* cessationOfOperation (5),
* certificateHold (6) }
*
*/
public class CRLDistributionPoint implements ASN1Value {
// at most one of the two following may be specified:
private GeneralNames fullName;
private RDN relativeName;
// cache encoding of fullName
private ANY fullNameEncoding;
private BitArray reasons; // optional, may be null
private GeneralNames CRLIssuer; // optional, may be null
private ANY CRLIssuerEncoding;
// default constructor does nothing.
/**
* Returns the fullName
of the DistributionPointName
, which may be null
.
*/
public GeneralNames getFullName() {
return fullName;
}
/**
* Returns the relativeName
of the DistributionPointName
, which may be null
.
*/
public RDN getRelativeName() {
return relativeName;
}
/**
* Sets the fullName
of the DistributionPointName
. It may be set to null
.
* If it is set to a non-null value, relativeName
will be
* set to null
, because at most one of these two attributes
* can be specified at a time.
*
* @exception GeneralNamesException If an error occurs encoding the
* name.
*/
public void setFullName(GeneralNames fullName)
throws GeneralNamesException, IOException {
this.fullName = fullName;
if (fullName != null) {
// encode the name to catch any problems with it
DerOutputStream derOut = new DerOutputStream();
fullName.encode(derOut);
try {
ANY raw = new ANY(derOut.toByteArray());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
raw.encodeWithAlternateTag(Tag.get(0), bos);
fullNameEncoding = new ANY(bos.toByteArray());
} catch (InvalidBERException e) {
// assume this won't happen, since it would imply a bug
// in DerOutputStream
throw new GeneralNamesException(e.toString());
}
this.relativeName = null;
}
}
/**
* Sets the relativeName
of the DistributionPointName
. It may be set to null
.
* If it is set to a non-null value, fullName
will be
* set to null
, because at most one of these two attributes
* can be specified at a time.
*/
public void setRelativeName(RDN relativeName) {
this.relativeName = relativeName;
if (relativeName != null) {
this.fullName = null;
}
}
/**
* Returns the reason flags for this distribution point. May be null
.
*/
public BitArray getReasons() {
return reasons;
}
/**
* Sets the reason flags for this distribution point. May be set to null
.
*/
public void setReasons(BitArray reasons) {
this.reasons = reasons;
}
/**
* Returns the CRLIssuer for the CRL at this distribution point.
* May be null
.
*/
public GeneralNames getCRLIssuer() {
return CRLIssuer;
}
/**
* Sets the CRLIssuer for the CRL at this distribution point.
* May be set to null
.
*
* @exception GeneralNamesException If an error occurs encoding the name.
*/
public void setCRLIssuer(GeneralNames CRLIssuer)
throws GeneralNamesException, IOException {
this.CRLIssuer = CRLIssuer;
if (CRLIssuer != null) {
// encode the name to catch any problems with it
DerOutputStream derOut = new DerOutputStream();
CRLIssuer.encode(derOut);
try {
ANY raw = new ANY(derOut.toByteArray());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
raw.encodeWithAlternateTag(Tag.get(2), bos);
CRLIssuerEncoding = new ANY(bos.toByteArray());
} catch (InvalidBERException e) {
throw new GeneralNamesException(e.toString());
}
}
}
/////////////////////////////////////////////////////////////
// DER encoding
/////////////////////////////////////////////////////////////
private static final Tag TAG = SEQUENCE.TAG;
@Override
public Tag getTag() {
return TAG;
}
@Override
public void encode(OutputStream ostream) throws IOException {
encode(TAG, ostream);
}
@Override
public void encode(Tag implicitTag, OutputStream ostream)
throws IOException {
SEQUENCE seq = new SEQUENCE();
DerOutputStream derOut;
try {
// Encodes the DistributionPointName. Because DistributionPointName
// is a CHOICE, the [0] tag is forced to be EXPLICIT.
if (fullName != null) {
EXPLICIT distPoint = new EXPLICIT(Tag.get(0), fullNameEncoding);
seq.addElement(distPoint);
} else if (relativeName != null) {
derOut = new DerOutputStream();
relativeName.encode(derOut);
ANY rn = new ANY(derOut.toByteArray());
EXPLICIT raw = new EXPLICIT(Tag.get(1), rn);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
raw.encode(bos);
ANY distPointName = new ANY(bos.toByteArray());
EXPLICIT distPoint = new EXPLICIT(Tag.get(0), distPointName);
seq.addElement(distPoint);
}
// Encodes the ReasonFlags.
if (reasons != null) {
derOut = new DerOutputStream();
derOut.putUnalignedBitString(reasons);
ANY raw = new ANY(derOut.toByteArray());
ByteArrayOutputStream bos = new ByteArrayOutputStream();
raw.encodeWithAlternateTag(Tag.get(1), bos);
ANY reasonEncoding = new ANY(bos.toByteArray());
seq.addElement(Tag.get(1), reasonEncoding);
}
// Encodes the CRLIssuer
if (CRLIssuer != null) {
seq.addElement(Tag.get(2), CRLIssuerEncoding);
}
seq.encode(implicitTag, ostream);
} catch (InvalidBERException e) {
// this shouldn't happen unless there is a bug in one of
// the Sun encoding classes
throw new IOException(e.toString());
}
}
// Template singleton
private static Template templateInstance = new Template();
/**
* Returns an instance of a template for decoding a CRLDistributionPoint.
*/
public static Template getTemplate() {
return templateInstance;
}
public static void main(String[] args) throws GeneralNamesException, IOException, InvalidBERException {
try (FileOutputStream fos = new FileOutputStream(args[0]);
ByteArrayOutputStream bos = new ByteArrayOutputStream()) {
if (args.length != 1) {
System.out.println("Usage: CRLDistributionPoint ");
System.exit(-1);
}
SEQUENCE cdps = new SEQUENCE();
// URI only
CRLDistributionPoint cdp = new CRLDistributionPoint();
URIName uri = new URIName("http://www.mycrl.com/go/here");
GeneralNames generalNames = new GeneralNames();
generalNames.addElement(uri);
cdp.setFullName(generalNames);
cdps.addElement(cdp);
// DN only
cdp = new CRLDistributionPoint();
X500Name dn = new X500Name("CN=Otis Smith,E=otis@fedoraproject.org" +
",OU=Certificate Server,O=Fedora,C=US");
generalNames = new GeneralNames();
generalNames.addElement(dn);
cdp.setFullName(generalNames);
cdps.addElement(cdp);
// DN + reason
BitArray ba = new BitArray(5, new byte[] { (byte) 0x28 });
cdp = new CRLDistributionPoint();
cdp.setFullName(generalNames);
cdp.setReasons(ba);
cdps.addElement(cdp);
// relative DN + reason + crlIssuer
cdp = new CRLDistributionPoint();
RDN rdn = new RDN("OU=foobar dept");
cdp.setRelativeName(rdn);
cdp.setReasons(ba);
cdp.setCRLIssuer(generalNames);
cdps.addElement(cdp);
cdps.encode(bos);
byte[] encoded = bos.toByteArray();
fos.write(encoded);
SEQUENCE.OF_Template seqt = new SEQUENCE.OF_Template(getTemplate());
cdps = (SEQUENCE) ASN1Util.decode(seqt, encoded);
int size = cdps.size();
System.out.println("Total number of CDPs: " + size);
for (int i = 0; i < size; i++) {
System.out.println("\nCDP " + i);
cdp = (CRLDistributionPoint) cdps.elementAt(i);
GeneralNames gn = cdp.getFullName();
if (gn == null) {
System.out.println("No full name");
} else {
System.out.println(gn);
}
rdn = cdp.getRelativeName();
if (rdn == null) {
System.out.println("No relative name");
} else {
System.out.println(rdn);
}
if (cdp.getReasons() == null) {
System.out.println("No reasons");
} else {
System.out.println(cdp.getReasons());
}
gn = cdp.getCRLIssuer();
if (gn == null) {
System.out.println("No cRLIssuer");
} else {
System.out.println(gn);
}
}
System.out.println("Done");
}
}
/**
* Template for decoding CRLDistributionPoint.
*/
public static class Template implements ASN1Template {
@Override
public boolean tagMatch(Tag tag) {
return TAG.equals(tag);
}
@Override
public ASN1Value decode(InputStream istream)
throws IOException, InvalidBERException {
return decode(TAG, istream);
}
@Override
public ASN1Value decode(Tag implicitTag, InputStream istream)
throws IOException, InvalidBERException {
CRLDistributionPoint cdp = new CRLDistributionPoint();
//
// construct the top-level sequence
//
SEQUENCE.Template seqt = SEQUENCE.getTemplate();
// distributionPoint
seqt.addOptionalElement(
new EXPLICIT.Template(Tag.get(0), ANY.getTemplate()));
// reasons
seqt.addOptionalElement(Tag.get(1), BIT_STRING.getTemplate());
// cRLIssuer
// This will have a tag of 2, but we can't say that here
// because ANYs can't have implicit tags. We don't need to say
// it, because we do check the tags on the other two elements
// in the sequence, so we'll know if we get this one.
seqt.addOptionalElement(ANY.getTemplate());
//
// decode the top-level sequence
//
SEQUENCE top = (SEQUENCE) seqt.decode(implicitTag, istream);
// decode the distribution point name
if (top.elementAt(0) != null) {
EXPLICIT exp = (EXPLICIT) top.elementAt(0);
ANY distPoint = (ANY) exp.getContent();
if (distPoint.getTag().equals(Tag.get(0))) {
// fullName
try {
DerValue dv = new DerValue(distPoint.getEncoded());
//toFile("encodedFullName", distPoint.getEncoded());
dv.resetTag(DerValue.tag_Sequence);
cdp.setFullName(new GeneralNames(dv));
} catch (GeneralNamesException e) {
throw new InvalidBERException("fullName: " + e.toString());
} catch (IOException e) {
throw new InvalidBERException("fullName: " + e.toString());
}
} else if (distPoint.getTag().equals(Tag.get(1))) {
// relative name
try {
DerValue dv = new DerValue(distPoint.getEncoded());
/* dv is as follows:
0 12: [1] {
2 10: SET {
4 8: SEQUENCE {
6 3: OBJECT IDENTIFIER commonName (2 5 4 3)
11 1: PrintableString 'x'
: }
: }
: }
*/
dv = dv.data.getDerValue(); // skipping the tag
/* after the skipping, we have:
0 10: SET {
2 8: SEQUENCE {
4 3: OBJECT IDENTIFIER commonName (2 5 4 3)
9 1: PrintableString 'x'
: }
: }
*/
dv.resetTag(DerValue.tag_Set);
cdp.setRelativeName(new RDN(dv));
} catch (IOException e) {
throw new InvalidBERException("relativeName " +
e.toString());
}
} else {
throw new InvalidBERException(
"Unknown tag " + distPoint.getTag() +
" in distributionPoint");
}
}
// decode the reasons
if (top.elementAt(1) != null) {
BIT_STRING bs = (BIT_STRING) top.elementAt(1);
byte[] bits = bs.getBits();
cdp.setReasons(
new BitArray((bits.length * 8) - bs.getPadCount(), bits));
}
// decode the cRLIssuer
if (top.elementAt(2) != null) {
ANY issuer = (ANY) top.elementAt(2);
if (!issuer.getTag().equals(Tag.get(2))) {
throw new InvalidBERException("Invalid tag " + issuer.getTag());
}
try {
DerValue dv = new DerValue(issuer.getEncoded());
dv.resetTag(DerValue.tag_Sequence);
cdp.setCRLIssuer(new GeneralNames(dv));
} catch (GeneralNamesException e) {
throw new InvalidBERException("cRLIssuer " + e.toString());
} catch (IOException e) {
throw new InvalidBERException("cRLIssuer " + e.toString());
}
}
return cdp;
}
}
}
CRLDistributionPointsExtension.java 0000664 0000000 0000000 00000032151 14565430767 0034022 0 ustar 00root root 0000000 0000000 jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.x509;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.cert.CertificateException;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import org.mozilla.jss.asn1.ASN1Util;
import org.mozilla.jss.asn1.InvalidBERException;
import org.mozilla.jss.asn1.SEQUENCE;
import org.mozilla.jss.netscape.security.util.BitArray;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* An extension that tells applications where to find the CRL for
* this certificate.
*
*
* cRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint
*
* DistributionPoint ::= SEQUENCE {
* distributionPoint [0] DistributionPointName OPTIONAL,
* reasons [1] ReasonFlags OPTIONAL,
* cRLIssuer [2] GeneralNames OPTIONAL }
*
* DistributionPointName ::= CHOICE {
* fullName [0] GeneralNames,
* nameRelativeToCRLIssuer [1] RelativeDistinguishedName }
*
* ReasonFlags ::= BIT STRING {
* unused (0),
* keyCompromise (1),
* cACompromise (2),
* affiliationChanged (3),
* superseded (4),
* cessationOfOperation (5),
* certificateHold (6) }
*
*/
public class CRLDistributionPointsExtension extends Extension
implements CertAttrSet {
/**
*
*/
private static final long serialVersionUID = 8551761833349709229L;
private static final Logger logger = LoggerFactory.getLogger(CRLDistributionPointsExtension.class);
// vector of CRLDistributionPoint
private SEQUENCE distributionPoints = new SEQUENCE();
// Cached DER-encoding to improve performance.
private byte[] cachedEncoding = null;
/**
* This constructor is called by the CertificateExtensions class to decode
* an extension whose OID indicates it is a CRLDistributionsPoints
* extension.
*/
public CRLDistributionPointsExtension(Boolean critical, Object value)
//throws IOException
{
try {
this.extensionId = PKIXExtensions.CRLDistributionPoints_Id;
this.critical = critical.booleanValue();
this.extensionValue = ((byte[]) value).clone();
// decode the value
try {
SEQUENCE.OF_Template seqOfCRLDP =
new SEQUENCE.OF_Template(CRLDistributionPoint.getTemplate());
distributionPoints =
(SEQUENCE) ASN1Util.decode(seqOfCRLDP, extensionValue);
} catch (InvalidBERException e) {
throw new IOException("Invalid BER-encoding: " + e, e);
}
} catch (IOException e) {
logger.error("Error decoding CRLDistributionPoints", e);
//throw e;
}
}
/**
* The Object Identifier for this extension.
*/
public static final String OID = "2.5.29.31";
/**
* Creates a new CRLDistributionPoints extension, with the given
* distribution point as the first element.
*/
public CRLDistributionPointsExtension(CRLDistributionPoint dp) {
this.extensionId = PKIXExtensions.CRLDistributionPoints_Id;
this.critical = false;
distributionPoints.addElement(dp);
}
/**
* Adds an additional distribution point to the end of the sequence.
*/
public void addPoint(CRLDistributionPoint dp) {
distributionPoints.addElement(dp);
cachedEncoding = null;
}
/**
* Returns the number of distribution points in the sequence.
*/
public int getNumPoints() {
return distributionPoints.size();
}
/**
* Returns the DistributionPoint at the given index in the sequence.
*/
public CRLDistributionPoint getPointAt(int index) {
return (CRLDistributionPoint) distributionPoints.elementAt(index);
}
/**
* Sets the criticality of this extension. PKIX dictates that this
* extension SHOULD NOT be critical, so applications can make it critical
* if they have a very good reason. By default, the extension is not
* critical.
*/
@Override
public void setCritical(boolean critical) {
this.critical = critical;
}
/**
* Encodes this extension to the given DerOutputStream.
* This method re-encodes each time it is called, so it is not very
* efficient.
*/
@Override
public void encode(DerOutputStream out) throws IOException {
extensionValue = ASN1Util.encode(distributionPoints);
super.encode(out);
}
/**
* Should be called if any change is made to this data structure
* so that the cached DER encoding can be discarded.
*/
public void flushCachedEncoding() {
cachedEncoding = null;
}
/////////////////////////////////////////////////////////////
// CertAttrSet interface
// This interface is not really appropriate for this extension
// because it is so complicated. Therefore, we only provide a
// minimal implementation.
/////////////////////////////////////////////////////////////
public static final String NAME = "CRLDistributionPoints";
@Override
public String toString() {
return NAME;
}
/**
* DER-encodes this extension to the given OutputStream.
*/
@Override
public void encode(OutputStream ostream)
throws CertificateException, IOException {
if (cachedEncoding == null) {
// only re-encode if necessary
DerOutputStream tmp = new DerOutputStream();
encode(tmp);
cachedEncoding = tmp.toByteArray();
}
ostream.write(cachedEncoding);
}
@Override
public void decode(InputStream in)
throws CertificateException, IOException {
throw new IOException("Not supported");
}
@Override
public void set(String name, Object obj)
throws CertificateException, IOException {
throw new IOException("Attribute name not recognized by " +
"CertAttrSet:CRLDistributionPointsExtension");
}
@Override
public Object get(String name)
throws CertificateException, IOException {
throw new IOException("Attribute name not recognized by " +
"CertAttrSet:CRLDistributionPointsExtension");
}
@Override
public void delete(String name)
throws CertificateException, IOException {
throw new IOException("Attribute name not recognized by " +
"CertAttrSet:CRLDistributionPointsExtension");
}
/*
* TODO use an empty collection to generate these
*/
@Override
public Enumeration getAttributeNames() {
return (new Vector()).elements();
}
@Override
public String getName() {
return NAME;
}
/**
* Test driver.
*/
public static void main(String args[]) {
BufferedOutputStream bos = null;
try {
if (args.length != 1) {
System.out.println("Usage: CRLDistributionPointsExtentions " +
"");
System.exit(-1);
}
bos = new BufferedOutputStream(
new FileOutputStream(args[0]));
// URI only
CRLDistributionPoint cdp = new CRLDistributionPoint();
URIName uri = new URIName("http://www.mycrl.com/go/here");
GeneralNames generalNames = new GeneralNames();
generalNames.addElement(uri);
cdp.setFullName(generalNames);
CRLDistributionPointsExtension crldpExt =
new CRLDistributionPointsExtension(cdp);
// DN only
cdp = new CRLDistributionPoint();
X500Name dn = new X500Name("CN=Otis Smith,E=otis@fedoraproject.org" +
",OU=Certificate Server,O=Fedora,C=US");
generalNames = new GeneralNames();
generalNames.addElement(dn);
cdp.setFullName(generalNames);
crldpExt.addPoint(cdp);
// DN + reason
BitArray ba = new BitArray(5, new byte[] { (byte) 0x28 });
cdp = new CRLDistributionPoint();
cdp.setFullName(generalNames);
cdp.setReasons(ba);
crldpExt.addPoint(cdp);
// relative DN + reason + crlIssuer
cdp = new CRLDistributionPoint();
RDN rdn = new RDN("OU=foobar dept");
cdp.setRelativeName(rdn);
cdp.setReasons(ba);
cdp.setCRLIssuer(generalNames);
crldpExt.addPoint(cdp);
crldpExt.setCritical(true);
crldpExt.encode(bos);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (bos != null) {
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* Represents a reason that a cert may be revoked. These reasons are
* expressed in a ReasonFlags bit string.
*/
public static class Reason {
private String name;
private byte bitMask;
private Reason() {
}
private Reason(String name, byte bitMask) {
this.name = name;
this.bitMask = bitMask;
map.put(name, this);
list.addElement(this);
}
private static Hashtable map = new Hashtable<>();
private static Vector list = new Vector<>();
public static Reason fromString(String name) {
return map.get(name);
}
public String getName() {
return name;
}
public byte getBitMask() {
return bitMask;
}
/**
* Given a bit array representing reason flags, extracts the reasons
* and returns them as an array.
*
* @param bitFlags A bit vector containing reason flags.
* @return An array of reasons contained in the bit vector.
* May be zero-length but will not be null.
*/
public static Reason[] bitArrayToReasonArray(byte bitFlags) {
return bitArrayToReasonArray(new byte[] { bitFlags });
}
/**
* Given a bit array representing reason flags, extracts the reasons
* and returns them as an array. Currently, only the first byte
* of the bitflags are examined.
*
* @param bitFlags A bit vector containing reason flags. The format
* is big-endian (MSB first). Only the first byte is examined.
* @return An array of reasons contained in the bit vector.
* May be zero-length but will not be null.
*/
public static Reason[] bitArrayToReasonArray(byte[] bitFlags) {
byte first = bitFlags[0];
int size = list.size();
Vector result = new Vector<>();
for (int i = 0; i < size; i++) {
Reason r = list.elementAt(i);
byte b = r.getBitMask();
if ((first & b) != 0) {
result.addElement(r);
}
}
size = result.size();
Reason[] retval = new Reason[size];
for (int i = 0; i < size; i++) {
retval[i] = result.elementAt(i);
}
return retval;
}
public static final Reason UNUSED =
new Reason("unused", (byte) 0x80);
public static final Reason KEY_COMPROMISE =
new Reason("keyCompromise", (byte) 0x40);
public static final Reason CA_COMPROMISE =
new Reason("cACompromise", (byte) 0x20);
public static final Reason AFFILIATION_CHANGED =
new Reason("affiliationChanged", (byte) 0x10);
public static final Reason SUPERSEDED =
new Reason("superseded", (byte) 0x08);
public static final Reason CESSATION_OF_OPERATION =
new Reason("cessationOfOperation", (byte) 0x04);
public static final Reason CERTIFICATE_HOLD =
new Reason("certificateHold", (byte) 0x02);
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509/CRLExtensions.java 0000664 0000000 0000000 00000021344 14565430767 0030471 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.x509;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.security.cert.CRLException;
import java.security.cert.CertificateException;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import org.mozilla.jss.netscape.security.util.DerInputStream;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
/**
* This class defines the CRL Extensions.
*
* @author Hemma Prafullchandra
* @version 1.4
*/
public class CRLExtensions extends Vector {
/**
*
*/
private static final long serialVersionUID = 365767738692986418L;
private Hashtable map;
// Parse the encoded extension
private void parseExtension(Extension ext) throws X509ExtensionException {
try {
Class> extClass = OIDMap.getClass(ext.getExtensionId());
if (extClass == null) { // Unsupported extension
if (ext.isCritical()) {
throw new IOException("Unsupported CRITICAL extension: "
+ ext.getExtensionId());
} else {
map.put(ext.getExtensionId().toString(), ext);
addElement(ext);
return;
}
}
Class>[] params = { Boolean.class, Object.class };
Constructor> cons = extClass.getConstructor(params);
byte[] extData = ext.getExtensionValue();
int extLen = extData.length;
Object value = Array.newInstance(byte.class, extLen);
for (int i = 0; i < extLen; i++) {
Array.setByte(value, i, extData[i]);
}
Object[] passed = new Object[] { Boolean.valueOf(ext.isCritical()),
value };
CertAttrSet crlExt = (CertAttrSet) cons.newInstance(passed);
map.put(crlExt.getName(), (Extension) crlExt);
addElement((Extension) crlExt);
} catch (InvocationTargetException invk) {
throw new X509ExtensionException(
invk.getTargetException().getMessage());
} catch (Exception e) {
throw new X509ExtensionException(e.toString());
}
}
/**
* Default constructor.
*/
public CRLExtensions() {
map = new Hashtable<>();
}
/**
* Create the object, decoding the values from the passed DER stream.
*
* @param in the DerInputStream to read the Extension from.
* @exception CRLException on decoding errors.
* @exception X509ExtensionException on extension handling errors.
*/
public CRLExtensions(DerInputStream in)
throws CRLException, X509ExtensionException {
map = new Hashtable<>();
try {
DerValue[] exts = in.getSequence(5);
for (int i = 0; i < exts.length; i++) {
Extension ext = new Extension(exts[i]);
parseExtension(ext);
}
} catch (IOException e) {
throw new CRLException("Parsing error: " + e.toString());
}
}
/**
* Decode the extensions from the InputStream.
*
* @param in the InputStream to unmarshal the contents from.
* @exception CRLException on decoding or validity errors.
* @exception X509ExtensionException on extension handling errors.
*/
public void decode(InputStream in)
throws CRLException, X509ExtensionException {
try {
DerValue val = new DerValue(in);
DerInputStream str = val.toDerInputStream();
map = new Hashtable<>();
DerValue[] exts = str.getSequence(5);
for (int i = 0; i < exts.length; i++) {
Extension ext = new Extension(exts[i]);
parseExtension(ext);
}
} catch (IOException e) {
throw new CRLException("Parsing error: " + e.toString());
}
}
/**
* Encode the extensions in DER form to the stream.
*
* @param out the DerOutputStream to marshal the contents to.
* @param isExplicit the tag indicating whether this is an entry
* extension or a CRL extension.
* @exception CRLException on encoding errors.
*/
public void encode(OutputStream out, boolean isExplicit)
throws CRLException {
try (DerOutputStream tmp = new DerOutputStream()) {
// #381559
if (size() == 0)
return;
DerOutputStream extOut = new DerOutputStream();
for (int i = 0; i < size(); i++) {
Object thisOne = elementAt(i);
if (thisOne instanceof CertAttrSet)
((CertAttrSet) thisOne).encode(extOut);
else if (thisOne instanceof Extension)
((Extension) thisOne).encode(extOut);
else
throw new CRLException("Illegal extension object");
}
DerOutputStream seq = new DerOutputStream();
seq.write(DerValue.tag_Sequence, extOut);
if (isExplicit) {
tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT,
true, (byte) 0), seq);
out.write(tmp.toByteArray());
} else {
out.write(seq.toByteArray());
}
} catch (IOException e) {
throw new CRLException("Encoding error: " + e.toString());
} catch (CertificateException e) {
throw new CRLException("Encoding error: " + e.toString());
}
}
/**
* Get the extension with this alias.
*
* @param alias the identifier string for the extension to retrieve.
* @exception X509ExtensionException on extension handling errors.
*/
public Extension get(String alias) throws X509ExtensionException {
X509AttributeName attr = new X509AttributeName(alias);
String name;
String id = attr.getPrefix();
if (id.equalsIgnoreCase(X509CertImpl.NAME)) { // fully qualified
int index = alias.lastIndexOf(".");
name = alias.substring(index + 1);
} else
name = alias;
Extension ext = map.get(name);
if (ext == null)
throw new X509ExtensionException("No extension found with name: "
+ alias);
return ext;
}
/**
* Set the extension value with this alias.
*
* @param alias the identifier string for the extension to set.
* @param obj the Object to set the extension identified by the
* alias.
* @exception IOException on errors.
*/
public void set(String alias, Extension obj) throws IOException {
map.put(alias, obj);
addElement(obj);
}
/**
* Return an enumeration of names of the extensions.
*
* @return an enumeration of the names of the extensions in this CRL.
*/
public Enumeration getElements() {
return (map.elements());
}
@Override
public synchronized int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((map == null) ? 0 : map.hashCode());
return result;
}
@Override
public synchronized boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
CRLExtensions other = (CRLExtensions) obj;
if (map == null) {
if (other.map != null)
return false;
} else if (!map.equals(other.map))
return false;
return true;
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509/CRLNumberExtension.java 0000664 0000000 0000000 00000016501 14565430767 0031456 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.x509;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Array;
import java.math.BigInteger;
import java.util.Enumeration;
import java.util.Vector;
import org.mozilla.jss.netscape.security.util.BigInt;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
/**
* Represent the CRL Number Extension.
*
*
* This extension, if present, conveys a monotonically increasing sequence number for each CRL issued by a given CA
* through a specific CA X.500 Directory entry or CRL distribution point. This extension allows users to easily
* determine when a particular CRL supersedes another CRL.
*
* @author Hemma Prafullchandra
* @version 1.2
* @see Extension
* @see CertAttrSet
*/
public class CRLNumberExtension extends Extension
implements CertAttrSet {
/**
*
*/
private static final long serialVersionUID = 2992307666566322402L;
/**
* Attribute name.
*/
public static final String NAME = "CRLNumber";
public static final String NUMBER = "value";
private BigInt crlNumber = null;
// Encode this extension value
private void encodeThis() throws IOException {
if (crlNumber == null)
throw new IOException("Unintialized CRL number extension");
try (DerOutputStream os = new DerOutputStream()) {
os.putInteger(this.crlNumber);
this.extensionValue = os.toByteArray();
}
}
/**
* Create a CRLNumberExtension with the integer value .
* The criticality is set to false.
*
* @param crlNum the value to be set for the extension.
*/
public CRLNumberExtension(int crlNum) throws IOException {
this.crlNumber = new BigInt(crlNum);
this.extensionId = PKIXExtensions.CRLNumber_Id;
this.critical = false;
encodeThis();
}
/**
* Create a CRLNumberExtension with the BigInteger value .
* The criticality is set to false.
*
* @param crlNum the value to be set for the extension.
*/
public CRLNumberExtension(BigInteger crlNum) throws IOException {
this.crlNumber = new BigInt(crlNum);
this.extensionId = PKIXExtensions.CRLNumber_Id;
this.critical = false;
encodeThis();
}
/**
* Create a CRLNumberExtension with the BigInteger value .
*
* @param critical true if the extension is to be treated as critical.
* @param crlNum the value to be set for the extension.
*/
public CRLNumberExtension(Boolean critical, BigInteger crlNum) throws IOException {
this.crlNumber = new BigInt(crlNum);
this.extensionId = PKIXExtensions.CRLNumber_Id;
this.critical = critical.booleanValue();
encodeThis();
}
/**
* Create the extension from the passed DER encoded value of the same.
*
* @param critical true if the extension is to be treated as critical.
* @param value Array of DER encoded bytes of the actual value.
* @exception IOException on error.
*/
public CRLNumberExtension(Boolean critical, Object value)
throws IOException {
this.extensionId = PKIXExtensions.CRLNumber_Id;
this.critical = critical.booleanValue();
int len = Array.getLength(value);
byte[] extValue = new byte[len];
for (int i = 0; i < len; i++) {
extValue[i] = Array.getByte(value, i);
}
this.extensionValue = extValue;
DerValue val = new DerValue(extValue);
this.crlNumber = val.getInteger();
}
/**
* Set the attribute value.
*/
@Override
public void set(String name, Object obj) throws IOException {
if (name.equalsIgnoreCase(NUMBER)) {
if (!(obj instanceof BigInteger)) {
throw new IOException("Attribute must be of type BigInteger.");
}
crlNumber = new BigInt((BigInteger) obj);
} else {
throw new IOException("Attribute name not recognized by"
+ " CertAttrSet:CRLNumber.");
}
}
/**
* Get the attribute value.
*/
@Override
public Object get(String name) throws IOException {
if (name.equalsIgnoreCase(NUMBER)) {
if (crlNumber == null)
return null;
else
return crlNumber.toBigInteger();
} else {
throw new IOException("Attribute name not recognized by"
+ " CertAttrSet:CRLNumber.");
}
}
/**
* Delete the attribute value.
*/
@Override
public void delete(String name) throws IOException {
if (name.equalsIgnoreCase(NUMBER)) {
crlNumber = null;
} else {
throw new IOException("Attribute name not recognized by"
+ " CertAttrSet:CRLNumber.");
}
}
/**
* Returns a printable representation of the CRLNumberExtension.
*/
@Override
public String toString() {
String s = super.toString() + "CRL Number: " +
((crlNumber == null) ? "" : crlNumber.toString())
+ "\n";
return (s);
}
/**
* Decode the extension from the InputStream.
*
* @param in the InputStream to unmarshal the contents from.
* @exception IOException on decoding or validity errors.
*/
@Override
public void decode(InputStream in) throws IOException {
throw new IOException("Method not to be called directly.");
}
/**
* Write the extension to the DerOutputStream.
*
* @param out the DerOutputStream to write the extension to.
* @exception IOException on encoding errors.
*/
@Override
public void encode(OutputStream out) throws IOException {
DerOutputStream tmp = new DerOutputStream();
if (this.extensionValue == null) {
this.extensionId = PKIXExtensions.CRLNumber_Id;
this.critical = false;
encodeThis();
}
super.encode(tmp);
out.write(tmp.toByteArray());
}
/**
* Return an enumeration of names of attributes existing within this
* attribute.
*/
@Override
public Enumeration getAttributeNames() {
Vector elements = new Vector<>();
elements.addElement(NUMBER);
return (elements.elements());
}
/**
* Return the name of this attribute.
*/
@Override
public String getName() {
return (NAME);
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509/CRLReasonExtension.java 0000664 0000000 0000000 00000017524 14565430767 0031463 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.x509;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.Vector;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
/**
* Represent the CRLReason Extension of CRL entry.
*
*
* This extension, if present, defines the identifies the reason for the certificate revocation.
*
* @author galperin
* @version $Revision$, $Date$
* @see Extension
* @see CertAttrSet
*/
public final class CRLReasonExtension extends Extension implements CertAttrSet {
/**
*
*/
private static final long serialVersionUID = 4544973296866779535L;
/**
* Canned instances for all revocation reasons
*/
public static final CRLReasonExtension UNSPECIFIED = new CRLReasonExtension(RevocationReason.UNSPECIFIED);
public static final CRLReasonExtension KEY_COMPROMISE = new CRLReasonExtension(RevocationReason.KEY_COMPROMISE);
public static final CRLReasonExtension CA_COMPROMISE = new CRLReasonExtension(RevocationReason.CA_COMPROMISE);
public static final CRLReasonExtension AFFILIATION_CHANGED = new CRLReasonExtension(
RevocationReason.AFFILIATION_CHANGED);
public static final CRLReasonExtension SUPERSEDED = new CRLReasonExtension(RevocationReason.SUPERSEDED);
public static final CRLReasonExtension CESSATION_OF_OPERATION = new CRLReasonExtension(
RevocationReason.CESSATION_OF_OPERATION);
public static final CRLReasonExtension CERTIFICATE_HOLD = new CRLReasonExtension(RevocationReason.CERTIFICATE_HOLD);
public static final CRLReasonExtension REMOVE_FROM_CRL = new CRLReasonExtension(RevocationReason.REMOVE_FROM_CRL);
public static final CRLReasonExtension PRIVILEGE_WITHDRAWN = new CRLReasonExtension(
RevocationReason.PRIVILEGE_WITHDRAWN);
public static final CRLReasonExtension AA_COMPROMISE = new CRLReasonExtension(RevocationReason.AA_COMPROMISE);
/**
* Attribute names.
*/
public static final String NAME = "CRLReason";
public static final String REASON = "value";
private RevocationReason mReason = null;
public RevocationReason getReason() {
return mReason;
}
/**
* Default constructor
*
*/
public CRLReasonExtension() {
this.extensionId = PKIXExtensions.ReasonCode_Id;
this.critical = false;
mReason = null;
}
/**
* Create extension value for specific revocation reason
*
*/
public CRLReasonExtension(RevocationReason reason) {
this.extensionId = PKIXExtensions.ReasonCode_Id;
this.critical = false;
mReason = reason;
}
public CRLReasonExtension(Boolean critical, RevocationReason reason)
throws IOException {
this.extensionId = PKIXExtensions.ReasonCode_Id;
this.critical = critical.booleanValue();
mReason = reason;
}
/**
* Create the object from the passed DER encoded value.
*
* @param value the DerValue decoded from the stream.
* @exception IOException on decoding errors.
*/
public CRLReasonExtension(Boolean critical, Object value)
throws IOException {
this.extensionId = PKIXExtensions.ReasonCode_Id;
this.critical = critical.booleanValue();
byte[] extValue = ((byte[]) value).clone();
this.extensionValue = extValue;
DerValue val = new DerValue(extValue);
int reasonCode = val.getEnumerated();
mReason = RevocationReason.fromInt(reasonCode);
if (mReason == null)
throw new IOException("Unknown revocation reason value " + reasonCode);
}
/**
* Set the attribute value.
*/
@Override
public void set(String name, Object obj) throws IOException {
if (!(obj instanceof RevocationReason)) {
throw new IOException("Attribute must be of type RevocationReason.");
}
if (name.equalsIgnoreCase(REASON)) {
mReason = (RevocationReason) obj;
} else {
throw new IOException("Name not recognized by CRLReason");
}
}
/**
* Get the attribute value.
*/
@Override
public Object get(String name) throws IOException {
if (name.equalsIgnoreCase(REASON)) {
return mReason;
} else {
throw new IOException("Name not recognized by CRLReason");
}
}
/**
* Delete the attribute value.
*/
@Override
public void delete(String name) throws IOException {
if (name.equalsIgnoreCase(REASON)) {
mReason = null;
} else {
throw new IOException("Name not recognized by CRLReason");
}
}
/**
* Returns a printable representation of the ReasonFlags.
*/
@Override
public String toString() {
String s = super.toString() + "CRL Reason [" + mReason + "]\n";
return (s);
}
/**
* Decode the extension from the InputStream.
*
* @param in the InputStream to unmarshal the contents from.
* @exception IOException on decoding or validity errors.
*/
@Override
public void decode(InputStream in) throws IOException {
throw new IOException("Method not to be called directly.");
}
// Encode this extension value
private void encodeThis() throws IOException {
if (mReason == null)
throw new IOException("Unintialized CRLReason extension");
try (DerOutputStream os = new DerOutputStream()) {
os.putEnumerated(mReason.toInt());
this.extensionValue = os.toByteArray();
}
}
/**
* Write the extension to the DerOutputStream.
*
* @param out the OutputStream to write the extension to.
* @exception IOException on encoding errors.
*/
@Override
public void encode(OutputStream out) throws IOException {
DerOutputStream tmp = new DerOutputStream();
if (this.extensionValue == null) {
encodeThis();
}
super.encode(tmp);
out.write(tmp.toByteArray());
}
/**
* Return an enumeration of names of attributes existing within this
* attribute.
*/
@Override
public Enumeration getAttributeNames() {
Vector elements = new Vector<>();
elements.addElement(REASON);
return (elements.elements());
}
/**
* Return the name of this attribute.
*/
@Override
public String getName() {
return (NAME);
}
@Override
public boolean equals(Object other) {
if (this == other)
return true;
else if (other instanceof CRLReasonExtension)
return ((CRLReasonExtension) other).mReason == mReason &&
((CRLReasonExtension) other).critical == critical;
else
return false;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((mReason == null) ? 0 : mReason.hashCode());
return result;
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509/CertAndKeyGen.java 0000664 0000000 0000000 00000022561 14565430767 0030416 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.x509;
import java.io.IOException;
import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.KeyPairGenerator;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.Date;
import org.mozilla.jss.netscape.security.pkcs.PKCS10;
/**
* Generate a pair of keys, and provide access to them. This class is
* provided primarily for ease of use.
*
*
* This provides some simple certificate management functionality. Specifically, it allows you to create self-signed
* X.509 certificates as well as PKCS 10 based certificate signing requests.
*
*
* Keys for some public key signature algorithms have algorithm parameters, such as DSS/DSA. Some sites' Certificate
* Authorities adopt fixed algorithm parameters, which speeds up some operations including key generation and signing.
* At this time, this interface
* does not provide a way to provide such algorithm parameters, e.g.
* by providing the CA certificate which includes those parameters.
*
*
* Also, note that at this time only signature-capable keys may be acquired through this interface. Diffie-Hellman keys,
* used for secure key exchange, may be supported later.
*
* @author David Brownell
* @author Hemma Prafullchandra
* @version 1.44
* @see PKCS10
* @see X509CertImpl
*/
public final class CertAndKeyGen {
/**
* Creates a CertAndKeyGen object for a particular key type
* and signature algorithm.
*
* @param keyType type of key, e.g. "RSA", "DSA"
* @param sigAlg name of the signature algorithm, e.g. "MD5WithRSA",
* "MD2WithRSA", "SHAwithDSA".
* @exception NoSuchAlgorithmException on unrecognized algorithms.
*/
public CertAndKeyGen(String keyType, String sigAlg)
throws NoSuchAlgorithmException {
keyGen = KeyPairGenerator.getInstance(keyType);
this.sigAlg = sigAlg;
}
// want "public void generate (X509Certificate)" ... inherit DSA/D-H param
/**
* Generates a random public/private key pair, with a given key
* size. Different algorithms provide different degrees of security
* for the same key size, because of the "work factor" involved in
* brute force attacks. As computers become faster, it becomes
* easier to perform such attacks. Small keys are to be avoided.
*
*
* Note that not all values of "keyBits" are valid for all algorithms, and not all public key algorithms are
* currently supported for use in X.509 certificates. If the algorithm you specified does not produce X.509
* compatible keys, an invalid key exception is thrown.
*
* @param keyBits the number of bits in the keys.
* @exception InvalidKeyException if the environment does not
* provide X.509 public keys for this signature algorithm.
*/
public void generate(int keyBits)
throws InvalidKeyException {
KeyPair pair;
try {
keyGen.initialize(keyBits);
pair = keyGen.generateKeyPair();
} catch (Exception e) {
throw new IllegalArgumentException(e.getMessage());
}
PublicKey publicKey = pair.getPublic();
if (publicKey instanceof X509Key) {
this.publicKey = (X509Key) publicKey;
} else {
throw new InvalidKeyException("public key " + publicKey +
" not an X509Key.");
}
privateKey = pair.getPrivate();
}
/**
* Returns the public key of the generated key pair.
*/
public X509Key getPublicKey() {
return publicKey;
}
/**
* Returns the private key of the generated key pair.
*
*
* Be extremely careful when handling private keys.
* When private keys are not kept secret, they lose their ability
* to securely authenticate specific entities ... that is a huge
* security risk!
*/
public PrivateKey getPrivateKey() {
return privateKey;
}
/**
* Returns a self-signed X.509v3 certificate for the public key.
* The certificate is immediately valid. No extensions.
*
*
* Such certificates normally are used to identify a "Certificate Authority" (CA). Accordingly, they will not always
* be accepted by other parties. However, such certificates are also useful when you are bootstrapping your security
* infrastructure, or deploying system prototypes.
*
* @param myname X.500 name of the subject (who is also the issuer)
* @param validity how long the certificate should be valid, in seconds
* @exception CertificateException on certificate handling errors.
* @exception InvalidKeyException on key handling errors.
* @exception SignatureException on signature handling errors.
* @exception NoSuchAlgorithmException on unrecognized algorithms.
* @exception NoSuchProviderException on unrecognized providers.
*/
public X509Certificate getSelfCertificate(X500Name myname, long validity)
throws CertificateException, InvalidKeyException, SignatureException,
NoSuchAlgorithmException, NoSuchProviderException {
X500Signer issuer;
X509CertImpl cert;
Date firstDate, lastDate;
try {
issuer = getSigner(myname);
firstDate = new Date();
lastDate = new Date();
lastDate.setTime(lastDate.getTime() + validity * 1000);
CertificateValidity interval =
new CertificateValidity(firstDate, lastDate);
X509CertInfo info = new X509CertInfo();
// Add all mandatory attributes
info.set(X509CertInfo.VERSION,
new CertificateVersion(CertificateVersion.V1));
info.set(X509CertInfo.SERIAL_NUMBER,
new CertificateSerialNumber((int) (firstDate.getTime() / 1000)));
AlgorithmId algID = issuer.getAlgorithmId();
info.set(X509CertInfo.ALGORITHM_ID,
new CertificateAlgorithmId(algID));
info.set(X509CertInfo.SUBJECT, new CertificateSubjectName(myname));
info.set(X509CertInfo.KEY, new CertificateX509Key(publicKey));
info.set(X509CertInfo.VALIDITY, interval);
info.set(X509CertInfo.ISSUER,
new CertificateIssuerName(issuer.getSigner()));
cert = new X509CertImpl(info);
cert.sign(privateKey, algID.getName());
return cert;
} catch (IOException e) {
throw new CertificateEncodingException("getSelfCertificate: " +
e.getMessage());
}
}
/**
* Returns a PKCS #10 certificate request. The caller uses either PKCS10.print
or
* PKCS10.toByteArray
operations on the result, to get the request in an appropriate
* transmission format.
*
*
* PKCS #10 certificate requests are sent, along with some proof of identity, to Certificate Authorities (CAs) which
* then issue X.509 public key certificates.
*
* @param myname X.500 name of the subject
* @exception InvalidKeyException on key handling errors.
* @exception SignatureException on signature handling errors.
*/
public PKCS10 getCertRequest(X500Name myname)
throws InvalidKeyException, SignatureException {
PKCS10 req = new PKCS10(publicKey);
try {
req.encodeAndSign(getSigner(myname));
} catch (CertificateException e) {
throw new SignatureException(sigAlg + " CertificateException");
} catch (IOException e) {
throw new SignatureException(sigAlg + " IOException");
} catch (NoSuchAlgorithmException e) {
// "can't happen"
throw new SignatureException(sigAlg + " unavailable?");
}
return req;
}
private X500Signer getSigner(X500Name me)
throws InvalidKeyException, NoSuchAlgorithmException {
Signature signature = Signature.getInstance(sigAlg);
signature.initSign(privateKey);
return new X500Signer(signature, me);
}
private String sigAlg;
private KeyPairGenerator keyGen;
private X509Key publicKey;
private PrivateKey privateKey;
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509/CertAttrSet.java 0000664 0000000 0000000 00000007751 14565430767 0030203 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.x509;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.cert.CertificateException;
import java.util.Enumeration;
/**
* This interface defines the methods required of a certificate attribute.
* Examples of X.509 certificate attributes are Validity, Issuer_Name, and
* Subject Name. A CertAttrSet may compromise one attribute or many
* attributes.
*
* A CertAttrSet itself can also be comprised of other sub-sets. In the case of X.509 V3 certificates, for example, the
* "extensions" attribute has subattributes, such as those for KeyUsage and AuthorityKeyIdentifier.
*
* @author Amit Kapoor
* @author Hemma Prafullchandra
* @version 1.9
* @see CertificateException
*/
public interface CertAttrSet {
/**
* Returns a short string describing this certificate attribute.
*
* @return value of this certificate attribute in
* printable form.
*/
@Override
String toString();
/**
* Encodes the attribute to the output stream in a format
* that can be parsed by the decode
method.
*
* @param out the OutputStream to encode the attribute to.
*
* @exception CertificateException on encoding or validity errors.
* @exception IOException on other errors.
*/
void encode(OutputStream out)
throws CertificateException, IOException;
/**
* Decodes the attribute in the input stream.
*
* @param in the InputStream to read the encoded attribute from.
*
* @exception CertificateException on decoding or validity errors.
* @exception IOException on other errors.
*/
void decode(InputStream in)
throws CertificateException, IOException;
/**
* Sets an attribute value within this CertAttrSet.
*
* @param name the name of the attribute (e.g. "x509.info.key")
* @param obj the attribute object.
*
* @exception CertificateException on attribute handling errors.
* @exception IOException on other errors.
*/
void set(String name, Object obj)
throws CertificateException, IOException;
/**
* Gets an attribute value for this CertAttrSet.
*
* @param name the name of the attribute to return.
* @return attribute value
* @exception CertificateException on attribute handling errors.
* @exception IOException on other errors.
*/
Object get(String name)
throws CertificateException, IOException;
/**
* Deletes an attribute value from this CertAttrSet.
*
* @param name the name of the attribute to delete.
*
* @exception CertificateException on attribute handling errors.
* @exception IOException on other errors.
*/
void delete(String name)
throws CertificateException, IOException;
/**
* Returns an enumeration of the names of the attributes existing within
* this attribute.
*
* @return an enumeration of the attribute names.
*/
Enumeration getAttributeNames();
/**
* Returns the name (identifier) of this CertAttrSet.
*
* @return the name of this CertAttrSet.
*/
String getName();
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509/CertException.java 0000664 0000000 0000000 00000012541 14565430767 0030544 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.x509;
/**
* CertException indicates one of a variety of certificate problems.
*
* @version 1.18
*
* @author David Brownell
* @author Amit Kapoor
* @author Hemma Prafullchandra
*/
public class CertException extends SecurityException {
// Zero is reserved.
/**
*
*/
private static final long serialVersionUID = -4046189948107720588L;
/** Indicates that the signature in the certificate is not valid. */
public static final int verf_INVALID_SIG = 1;
/** Indicates that the certificate was revoked, and so is invalid. */
public static final int verf_INVALID_REVOKED = 2;
/** Indicates that the certificate is not yet valid. */
public static final int verf_INVALID_NOTBEFORE = 3;
/** Indicates that the certificate has expired and so is not valid. */
public static final int verf_INVALID_EXPIRED = 4;
/**
* Indicates that a certificate authority in the certification
* chain is not trusted.
*/
public static final int verf_CA_UNTRUSTED = 5;
/** Indicates that the certification chain is too long. */
public static final int verf_CHAIN_LENGTH = 6;
/** Indicates an error parsing the ASN.1/DER encoding of the certificate. */
public static final int verf_PARSE_ERROR = 7;
/** Indicates an error constructing a certificate or certificate chain. */
public static final int err_CONSTRUCTION = 8;
/** Indicates a problem with the public key */
public static final int err_INVALID_PUBLIC_KEY = 9;
/** Indicates a problem with the certificate version */
public static final int err_INVALID_VERSION = 10;
/** Indicates a problem with the certificate format */
public static final int err_INVALID_FORMAT = 11;
/** Indicates a problem with the certificate encoding */
public static final int err_ENCODING = 12;
// Private data members
private int verfCode;
private String moreData;
/**
* Constructs a certificate exception using an error code
* (verf_*
) and a string describing the context
* of the error.
*/
public CertException(int code, String moredata) {
verfCode = code;
moreData = moredata;
}
/**
* Constructs a certificate exception using just an error code,
* without a string describing the context.
*/
public CertException(int code) {
verfCode = code;
}
/**
* Returns the error code with which the exception was created.
*/
public int getVerfCode() {
return verfCode;
}
/**
* Returns a string describing the context in which the exception
* was reported.
*/
public String getMoreData() {
return moreData;
}
/**
* Return a string corresponding to the error code used to create
* this exception.
*/
public String getVerfDescription() {
switch (verfCode) {
case verf_INVALID_SIG:
return "The signature in the certificate is not valid.";
case verf_INVALID_REVOKED:
return "The certificate has been revoked.";
case verf_INVALID_NOTBEFORE:
return "The certificate is not yet valid.";
case verf_INVALID_EXPIRED:
return "The certificate has expired.";
case verf_CA_UNTRUSTED:
return "The Authority which issued the certificate is not trusted.";
case verf_CHAIN_LENGTH:
return "The certificate path to a trusted authority is too long.";
case verf_PARSE_ERROR:
return "The certificate could not be parsed.";
case err_CONSTRUCTION:
return "There was an error when constructing the certificate.";
case err_INVALID_PUBLIC_KEY:
return "The public key was not in the correct format.";
case err_INVALID_VERSION:
return "The certificate has an invalid version number.";
case err_INVALID_FORMAT:
return "The certificate has an invalid format.";
case err_ENCODING:
return "Problem encountered while encoding the data.";
default:
return "Unknown code: " + verfCode;
}
}
/**
* Returns a string describing the certificate exception.
*/
@Override
public String toString() {
return "[Certificate Exception: " + getMessage() + "]";
}
/**
* Returns a string describing the certificate exception.
*/
@Override
public String getMessage() {
return getVerfDescription()
+ ((moreData != null)
? ("\n (" + moreData + ")") : "");
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509/CertParseError.java 0000664 0000000 0000000 00000002466 14565430767 0030677 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.x509;
//back out these changes until backwards compatibility with
//CertException is not an issue.
//import java.security.CertificateException;
/**
* CertException indicates one of a variety of certificate problems.
*
* @version 1.7
* @author David Brownell
*/
class CertParseError extends CertException {
/**
*
*/
private static final long serialVersionUID = -7623327377774730807L;
CertParseError(String where) {
super(CertException.verf_PARSE_ERROR, where);
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509/CertificateAlgorithmId.java 0000664 0000000 0000000 00000013406 14565430767 0032337 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.x509;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.Enumeration;
import java.util.Vector;
import org.mozilla.jss.netscape.security.util.DerInputStream;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
/**
* This class defines the AlgorithmId for the Certificate.
*
* @author Amit Kapoor
* @author Hemma Prafullchandra
* @version 1.7
*/
public class CertificateAlgorithmId implements CertAttrSet, Serializable {
/**
*
*/
private static final long serialVersionUID = 6084780721443376563L;
private AlgorithmId algId;
/**
* Identifier for this attribute, to be used with the
* get, set, delete methods of Certificate, x509 type.
*/
public static final String IDENT = "x509.info.algorithmID";
/**
* Sub attributes name for this CertAttrSet.
*/
public static final String NAME = "algorithmID";
public static final String ALGORITHM = "algorithm";
/**
* Default constructor for the certificate attribute.
*
* @param algId the Algorithm identifier
*/
public CertificateAlgorithmId(AlgorithmId algId) {
this.algId = algId;
}
/**
* Create the object, decoding the values from the passed DER stream.
*
* @param in the DerInputStream to read the serial number from.
* @exception IOException on decoding errors.
*/
public CertificateAlgorithmId(DerInputStream in) throws IOException {
DerValue val = in.getDerValue();
algId = AlgorithmId.parse(val);
}
/**
* Create the object, decoding the values from the passed stream.
*
* @param in the InputStream to read the serial number from.
* @exception IOException on decoding errors.
*/
public CertificateAlgorithmId(InputStream in) throws IOException {
DerValue val = new DerValue(in);
algId = AlgorithmId.parse(val);
}
/**
* Return the algorithm identifier as user readable string.
*/
@Override
public String toString() {
if (algId == null)
return "";
return (algId.toString() +
", OID = " + (algId.getOID()).toString() + "\n");
}
private void writeObject(ObjectOutputStream stream) throws IOException {
encode(stream);
}
private void readObject(ObjectInputStream stream) throws IOException {
decode(stream);
}
/**
* Encode the algorithm identifier in DER form to the stream.
*
* @param out the DerOutputStream to marshal the contents to.
* @exception IOException on errors.
*/
@Override
public void encode(OutputStream out) throws IOException {
DerOutputStream tmp = new DerOutputStream();
algId.encode(tmp);
out.write(tmp.toByteArray());
}
/**
* Decode the algorithm identifier from the passed stream.
*
* @param in the InputStream to unmarshal the contents from.
* @exception IOException on errors.
*/
@Override
public void decode(InputStream in) throws IOException {
DerValue derVal = new DerValue(in);
algId = AlgorithmId.parse(derVal);
}
/**
* Set the attribute value.
*/
@Override
public void set(String name, Object obj) throws IOException {
if (!(obj instanceof AlgorithmId)) {
throw new IOException("Attribute must be of type AlgorithmId.");
}
if (name.equalsIgnoreCase(ALGORITHM)) {
algId = (AlgorithmId) obj;
} else {
throw new IOException("Attribute name not recognized by " +
"CertAttrSet:CertificateAlgorithmId.");
}
}
/**
* Get the attribute value.
*/
@Override
public Object get(String name) throws IOException {
if (name.equalsIgnoreCase(ALGORITHM)) {
return (algId);
} else {
throw new IOException("Attribute name not recognized by " +
"CertAttrSet:CertificateAlgorithmId.");
}
}
/**
* Delete the attribute value.
*/
@Override
public void delete(String name) throws IOException {
if (name.equalsIgnoreCase(ALGORITHM)) {
algId = null;
} else {
throw new IOException("Attribute name not recognized by " +
"CertAttrSet:CertificateAlgorithmId.");
}
}
/**
* Return an enumeration of names of attributes existing within this
* attribute.
*/
@Override
public Enumeration getAttributeNames() {
Vector elements = new Vector<>();
elements.addElement(ALGORITHM);
return (elements.elements());
}
/**
* Return the name of this attribute.
*/
@Override
public String getName() {
return (NAME);
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509/CertificateChain.java 0000664 0000000 0000000 00000016220 14565430767 0031153 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.x509;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Serializable;
import java.io.StringWriter;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.mozilla.jss.netscape.security.pkcs.PKCS7;
import org.mozilla.jss.netscape.security.util.Cert;
import org.mozilla.jss.netscape.security.util.Utils;
public class CertificateChain implements Serializable {
private List certs = new ArrayList<>();
/**
* Constructs an empty certificate chain.
*/
public CertificateChain() {
}
/**
* constructs a certificate chain from a certificate.
*
* @param cert a certificate
*/
public CertificateChain(X509Certificate cert) {
if (cert == null) {
throw new IllegalArgumentException("Missing input certificate");
}
certs.add(cert);
}
/**
* constructs a certificate chain from a X509 certificate array.
*
* @param certs a certificate array.
*/
public CertificateChain(X509Certificate[] certs) {
if (certs == null) {
throw new IllegalArgumentException("Missing input certificates");
}
this.certs.addAll(Arrays.asList(certs));
}
/**
* Returns the certificate list.
*
* @return The certificate list.
*/
public List getCertificates() {
return certs;
}
/**
* returns the certificate at specified index in chain.
*
* @param index the index.
* @return the X509 certificate at the given index.
*/
public X509Certificate getCertificate(int index) {
return certs.get(index);
}
/**
* returns the first certificate in chain.
*
* @return the X509 certificate at the given index.
*/
public X509Certificate getFirstCertificate() {
return certs.get(0);
}
/**
* returns the certificate chain as an array of X509 certificates.
*
* @return an array of X509 Certificates.
*/
public X509Certificate[] getChain() {
return certs.toArray(new X509Certificate[certs.size()]);
}
/**
* Sorts certificate chain from root to leaf.
*/
public void sort() throws Exception {
X509Certificate[] certs = getChain();
certs = Cert.sortCertificateChain(certs);
this.certs.clear();
this.certs.addAll(Arrays.asList(certs));
}
public void encode(OutputStream out)
throws IOException {
encode(out, true);
}
/**
* encode in PKCS7 blob.
*/
public void encode(OutputStream out, boolean sort) throws IOException {
X509Certificate[] certs = getChain();
PKCS7 p7 = new PKCS7(certs);
p7.encodeSignedData(out, sort);
}
/**
* decode from PKCS7 blob.
*/
public void decode(InputStream in)
throws IOException {
PKCS7 p7 = new PKCS7(in);
certs.clear();
certs.addAll(Arrays.asList(p7.getCertificates()));
}
/**
* for serialization
*/
private void writeObject(java.io.ObjectOutputStream out)
throws IOException {
encode(out);
}
/**
* for serialization
*/
private void readObject(java.io.ObjectInputStream in)
throws IOException {
decode(in);
}
public void addCertificate(X509Certificate cert) {
certs.add(cert);
}
public void addCertificateChain(CertificateChain certChain) {
certs.addAll(certChain.certs);
}
public void addPKCS7(PKCS7 pkcs7) {
certs.addAll(Arrays.asList(pkcs7.getCertificates()));
}
/**
* Convert a series of PEM certificates or a PKCS #7 data into a certificate chain.
* This method will only accept a single chain, so it cannot be used to load CA bundle.
*/
public static CertificateChain fromPEMString(String input) throws Exception {
CertificateChain certChain = new CertificateChain();
StringBuilder sb = new StringBuilder();
String[] lines = input.split("\\r?\\n");
for (String line : lines) {
line = line.trim();
if (Cert.HEADER.equals(line)) {
sb.setLength(0);
} else if (Cert.FOOTER.equals(line)) {
byte[] bytes = Utils.base64decode(sb.toString());
certChain.addCertificate(new X509CertImpl(bytes));
} else if (PKCS7.HEADER.equals(line)) {
sb.setLength(0);
} else if (PKCS7.FOOTER.equals(line)) {
byte[] bytes = Utils.base64decode(sb.toString());
PKCS7 pkcs7 = new PKCS7(bytes);
certChain.addPKCS7(pkcs7);
} else {
sb.append(line);
}
}
// sort and validate the certificate chain
certChain.sort();
return certChain;
}
/**
* Convert the certificate chain into a series of PEM certificates.
*/
public String toPEMString() throws Exception {
// sort and validate the certificate chain
sort();
StringWriter sw = new StringWriter();
PrintWriter pw = new PrintWriter(sw, true);
for (X509Certificate cert : certs) {
pw.println(Cert.HEADER);
pw.print(Utils.base64encodeMultiLine(cert.getEncoded()));
pw.println(Cert.FOOTER);
}
return sw.toString();
}
/**
* Convert the certificate chain into a PKCS #7 object.
*/
public PKCS7 toPKCS7() throws Exception {
// sort and validate the certificate chain
sort();
// convert X509Certificate into X509CertImpl
List certImpls = new ArrayList<>();
for (X509Certificate cert : certs) {
certImpls.add(new X509CertImpl(cert.getEncoded()));
}
return new PKCS7(certImpls.toArray(new X509CertImpl[0]));
}
/**
* Converts the certificate chain to a readable string.
*/
@Override
public String toString() {
if (certs.isEmpty()) {
return "[]";
}
StringBuilder sb = new StringBuilder();
sb.append("[");
for (X509Certificate cert : certs) {
sb.append(cert);
}
sb.append("]");
return sb.toString();
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509/CertificateExtensions.java 0000664 0000000 0000000 00000023121 14565430767 0032266 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.x509;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.security.cert.CertificateException;
import java.util.Collections;
import java.util.Enumeration;
import java.util.LinkedHashMap;
import java.util.Vector;
import org.mozilla.jss.netscape.security.util.DerInputStream;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
/**
* This class defines the Extensions attribute for the Certificate.
*
* @author Amit Kapoor
* @author Hemma Prafullchandra
* @version 1.11
* @see CertAttrSet
*/
public class CertificateExtensions extends Vector
implements CertAttrSet {
/**
*
*/
private static final long serialVersionUID = -7172635300185788849L;
/**
* Identifier for this attribute, to be used with the
* get, set, delete methods of Certificate, x509 type.
*/
public static final String IDENT = "x509.info.extensions";
/**
* name
*/
public static final String NAME = "extensions";
private LinkedHashMap map;
// Parse the encoded extension
public void parseExtension(Extension ext) throws IOException {
try {
@SuppressWarnings("unchecked")
Class extClass = (Class) OIDMap.getClass(ext.getExtensionId());
if (extClass == null) { // Unsupported extension
map.put(ext.getExtensionId().toString(), ext);
addElement(ext);
return;
}
Class>[] params = { Boolean.class, Object.class };
Constructor cons = extClass.getConstructor(params);
byte[] extData = ext.getExtensionValue();
int extLen = extData.length;
Object value = Array.newInstance(byte.class, extLen);
for (int i = 0; i < extLen; i++) {
Array.setByte(value, i, extData[i]);
}
Object[] passed = new Object[] { Boolean.valueOf(ext.isCritical()),
value };
CertAttrSet certExt = cons.newInstance(passed);
if (certExt != null && certExt.getName() != null) {
map.put(certExt.getName(), (Extension) certExt);
addElement((Extension) certExt);
}
} catch (NoSuchMethodException e) {
throw new IOException(e);
} catch (InvocationTargetException e) {
Throwable t = e.getTargetException();
if (t instanceof IOException) {
throw (IOException)t;
}
throw new IOException(t);
} catch (Exception e) {
throw new IOException(e);
}
}
/**
* Default constructor for the certificate attribute.
*/
public CertificateExtensions() {
map = new LinkedHashMap<>();
}
/**
* Create the object, decoding the values from the passed DER stream.
*
* @param in the DerInputStream to read the Extension from.
* @exception IOException on decoding errors.
*/
public CertificateExtensions(DerInputStream in)
throws IOException {
map = new LinkedHashMap<>();
DerValue[] exts = in.getSequence(5);
for (int i = 0; i < exts.length; i++) {
Extension ext = new Extension(exts[i]);
parseExtension(ext);
}
}
/**
* Decode the extensions from the InputStream.
*
* @param in the InputStream to unmarshal the contents from.
* @exception IOException on decoding or validity errors.
*/
@Override
public void decode(InputStream in) throws IOException {
DerValue val = new DerValue(in);
DerInputStream str = val.toDerInputStream();
map = new LinkedHashMap<>();
DerValue[] exts = str.getSequence(5);
for (int i = 0; i < exts.length; i++) {
Extension ext = new Extension(exts[i]);
parseExtension(ext);
}
}
/**
* Decode the extensions from the InputStream.
*
* @param in the InputStream to unmarshal the contents from.
* @exception IOException on decoding or validity errors.
*/
public void decodeEx(InputStream in) throws IOException {
DerValue val = new DerValue(in);
DerInputStream str = null;
if (val.isConstructed() && val.isContextSpecific((byte) 3)) {
str = val.data;
} else {
str = val.toDerInputStream();
}
map = new LinkedHashMap<>();
DerValue[] exts = str.getSequence(5);
for (int i = 0; i < exts.length; i++) {
Extension ext = new Extension(exts[i]);
parseExtension(ext);
}
}
private void writeObject(ObjectOutputStream stream) throws CertificateException, IOException {
encode(stream);
}
private void readObject(ObjectInputStream stream) throws CertificateException, IOException {
decodeEx(stream);
}
/**
* Encode the extensions in DER form to the stream.
*
* @param out the DerOutputStream to marshal the contents to.
* @exception CertificateException on encoding errors.
* @exception IOException on errors.
*/
@Override
public void encode(OutputStream out)
throws CertificateException, IOException {
try (DerOutputStream tmp = new DerOutputStream()) {
DerOutputStream extOut = new DerOutputStream();
for (int i = 0; i < size(); i++) {
Object thisOne = elementAt(i);
if (thisOne instanceof CertAttrSet)
((CertAttrSet) thisOne).encode(extOut);
else if (thisOne instanceof Extension)
((Extension) thisOne).encode(extOut);
else
throw new CertificateException("Invalid extension object");
}
DerOutputStream seq = new DerOutputStream();
seq.write(DerValue.tag_Sequence, extOut);
tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 3),
seq);
out.write(tmp.toByteArray());
}
}
/**
* Set the attribute value.
*
* @param name the extension name used in the cache.
* @param obj the object to set.
* @exception IOException if the object could not be cached.
*/
@Override
public void set(String name, Object obj) throws IOException {
map.put(name, (Extension) obj);
addElement((Extension) obj);
}
/**
* Get the attribute value.
*
* @param name the extension name used in the lookup.
* @exception IOException if named extension is not found.
*/
@Override
public Object get(String name) throws IOException {
Object obj = map.get(name);
if (obj == null) {
throw new IOException("No extension found with name " + name);
}
return (obj);
}
/**
* Delete the attribute value.
*
* @param name the extension name used in the lookup.
* @exception IOException if named extension is not found.
*/
@Override
public void delete(String name) throws IOException {
Object obj = map.get(name);
if (obj == null) {
throw new IOException("No extension found with name " + name);
}
map.remove(name);
removeElement(obj);
}
public Enumeration getNames() {
return Collections.enumeration(map.keySet());
}
/**
* Return an enumeration of names of attributes existing within this
* attribute.
*/
public Enumeration getAttributes() {
return Collections.enumeration(map.values());
}
@Override
public Enumeration getAttributeNames() {
return getNames();
}
/**
* Return the name of this attribute.
*/
@Override
public String getName() {
return (NAME);
}
@Override
public synchronized int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((map == null) ? 0 : map.hashCode());
return result;
}
@Override
public synchronized boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
CertificateExtensions other = (CertificateExtensions) obj;
if (map == null) {
if (other.map != null)
return false;
} else if (!map.equals(other.map))
return false;
return true;
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509/CertificateIssuerExtension.java 0000664 0000000 0000000 00000017166 14565430767 0033312 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.x509;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Array;
import java.security.cert.CertificateException;
import java.util.Enumeration;
import java.util.Vector;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
/**
* Represent the CRL Certificate Issuer Extension.
*
*
* This CRL entry extension identifies the certificate issuer associated with an entry in an indirect CRL, i.e. a CRL
* that has the indirectCRL indicator set in its issuing distribution point extension.
*
* @see Extension
* @see CertAttrSet
*/
public class CertificateIssuerExtension extends Extension
implements CertAttrSet {
/**
*
*/
private static final long serialVersionUID = 8643788952936025986L;
/**
* Attribute name.
*/
public static final String NAME = "CertificateIssuer";
public static final String CERTIFICATE_ISSUER = "value";
/**
* The Object Identifier for this extension.
*/
public static final String OID = "2.5.29.29";
// private data members
GeneralNames names = null;
static {
try {
OIDMap.addAttribute(CertificateIssuerExtension.class.getName(),
OID, NAME);
} catch (CertificateException e) {
}
}
// Encode this extension
private void encodeThis() throws IOException {
DerOutputStream os = new DerOutputStream();
try {
names.encode(os);
} catch (GeneralNamesException e) {
throw new IOException(e);
}
this.extensionValue = os.toByteArray();
}
/**
* Create a CertificateIssuerExtension with the passed GeneralNames
* and criticality.
*
* @param critical true if the extension is to be treated as critical.
* @param names the GeneralNames for the issuer.
* @exception IOException on error.
*/
public CertificateIssuerExtension(Boolean critical, GeneralNames names)
throws IOException {
this.names = names;
this.extensionId = PKIXExtensions.CertificateIssuer_Id;
this.critical = critical.booleanValue();
encodeThis();
}
/**
* Create a CertificateIssuerExtension with the passed GeneralNames.
*
* @param names the GeneralNames for the issuer.
* @exception IOException on error.
*/
public CertificateIssuerExtension(GeneralNames names)
throws IOException {
this.names = names;
this.extensionId = PKIXExtensions.CertificateIssuer_Id;
this.critical = true;
encodeThis();
}
/**
* Create a default CertificateIssuerExtension.
*/
public CertificateIssuerExtension() {
extensionId = PKIXExtensions.CertificateIssuer_Id;
critical = false;
names = new GeneralNames();
}
/**
* Create the extension from the passed DER encoded value.
*
* @param critical true if the extension is to be treated as critical.
* @param value Array of DER encoded bytes of the actual value.
* @exception IOException on error.
*/
public CertificateIssuerExtension(Boolean critical, Object value)
throws IOException {
this.extensionId = PKIXExtensions.CertificateIssuer_Id;
this.critical = critical.booleanValue();
int len = Array.getLength(value);
byte[] extValue = new byte[len];
for (int i = 0; i < len; i++) {
extValue[i] = Array.getByte(value, i);
}
this.extensionValue = extValue;
DerValue val = new DerValue(extValue);
try {
names = new GeneralNames(val);
} catch (GeneralNamesException e) {
throw new IOException("CertificateIssuerExtension: " + e, e);
}
}
/**
* Returns a printable representation of the CertificateIssuerName.
*/
@Override
public String toString() {
if (names == null)
return "";
String s = super.toString() + "CertificateIssuerName [\n"
+ names.toString() + "]\n";
return (s);
}
/**
* Decode the extension from the InputStream.
*
* @param in the InputStream to unmarshal the contents from.
* @exception IOException on decoding or validity errors.
*/
@Override
public void decode(InputStream in) throws IOException {
throw new IOException("Method not to be called directly.");
}
/**
* Write the extension to the OutputStream.
*
* @param out the OutputStream to write the extension to.
* @exception IOException on encoding error.
*/
@Override
public void encode(OutputStream out) throws IOException {
DerOutputStream tmp = new DerOutputStream();
if (extensionValue == null) {
extensionId = PKIXExtensions.CertificateIssuer_Id;
critical = false;
encodeThis();
}
super.encode(tmp);
out.write(tmp.toByteArray());
}
/**
* Set the attribute value.
*/
@Override
public void set(String name, Object obj) throws IOException {
if (name.equalsIgnoreCase(CERTIFICATE_ISSUER)) {
if (!(obj instanceof GeneralNames)) {
throw new IOException("Attribute value should be of" +
" type GeneralNames.");
}
names = (GeneralNames) obj;
} else {
throw new IOException("Attribute name not recognized by " +
"CertAttrSet:CertificateIssuerName.");
}
}
/**
* Get the attribute value.
*/
@Override
public Object get(String name) throws IOException {
if (name.equalsIgnoreCase(CERTIFICATE_ISSUER)) {
return (names);
} else {
throw new IOException("Attribute name not recognized by " +
"CertAttrSet:CertificateIssuerName.");
}
}
/**
* Delete the attribute value.
*/
@Override
public void delete(String name) throws IOException {
if (name.equalsIgnoreCase(CERTIFICATE_ISSUER)) {
names = null;
} else {
throw new IOException("Attribute name not recognized by " +
"CertAttrSet:CertificateIssuerName.");
}
}
/**
* Return an enumeration of names of attributes existing within this
* attribute.
*/
@Override
public Enumeration getAttributeNames() {
Vector elements = new Vector<>();
elements.addElement(CERTIFICATE_ISSUER);
return (elements.elements());
}
/**
* Return the name of this attribute.
*/
@Override
public String getName() {
return (NAME);
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509/CertificateIssuerName.java 0000664 0000000 0000000 00000012311 14565430767 0032201 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.x509;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.Vector;
import org.mozilla.jss.netscape.security.util.DerInputStream;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
/**
* This class defines the X500Name attribute for the Certificate.
*
* @author Amit Kapoor
* @author Hemma Prafullchandra
* @version 1.6
* @see CertAttrSet
*/
public class CertificateIssuerName implements CertAttrSet {
/**
* Identifier for this attribute, to be used with the
* get, set, delete methods of Certificate, x509 type.
*/
public static final String IDENT = "x509.info.issuer";
/**
* Sub attributes name for this CertAttrSet.
*/
public static final String NAME = "issuer";
public static final String DN_NAME = "dname";
// Private data member
private X500Name dnName;
/**
* Default constructor for the certificate attribute.
*
* @param name the X500Name
*/
public CertificateIssuerName(X500Name name) {
this.dnName = name;
}
/**
* Create the object, decoding the values from the passed DER stream.
*
* @param in the DerInputStream to read the X500Name from.
* @exception IOException on decoding errors.
*/
public CertificateIssuerName(DerInputStream in) throws IOException {
dnName = new X500Name(in);
}
/**
* Create the object, decoding the values from the passed stream.
*
* @param in the InputStream to read the X500Name from.
* @exception IOException on decoding errors.
*/
public CertificateIssuerName(InputStream in) throws IOException {
DerValue derVal = new DerValue(in);
dnName = new X500Name(derVal);
}
/**
* Return the name as user readable string.
*/
@Override
public String toString() {
if (dnName == null)
return "";
return (dnName.toString());
}
/**
* Encode the name in DER form to the stream.
*
* @param out the DerOutputStream to marshal the contents to.
* @exception IOException on errors.
*/
@Override
public void encode(OutputStream out) throws IOException {
DerOutputStream tmp = new DerOutputStream();
dnName.encode(tmp);
out.write(tmp.toByteArray());
}
/**
* Decode the name in DER form from the stream.
*
* @param in the InputStream to marshal the contents from.
* @exception IOException on errors.
*/
@Override
public void decode(InputStream in) throws IOException {
DerValue derVal = new DerValue(in);
dnName = new X500Name(derVal);
}
/**
* Set the attribute value.
*/
@Override
public void set(String name, Object obj) throws IOException {
if (!(obj instanceof X500Name)) {
throw new IOException("Attribute must be of type X500Name.");
}
if (name.equalsIgnoreCase(DN_NAME)) {
this.dnName = (X500Name) obj;
} else {
throw new IOException("Attribute name not recognized by " +
"CertAttrSet:CertificateIssuerName.");
}
}
/**
* Get the attribute value.
*/
@Override
public Object get(String name) throws IOException {
if (name.equalsIgnoreCase(DN_NAME)) {
return (dnName);
} else {
throw new IOException("Attribute name not recognized by " +
"CertAttrSet:CertificateIssuerName.");
}
}
/**
* Delete the attribute value.
*/
@Override
public void delete(String name) throws IOException {
if (name.equalsIgnoreCase(DN_NAME)) {
dnName = null;
} else {
throw new IOException("Attribute name not recognized by " +
"CertAttrSet:CertificateIssuerName.");
}
}
/**
* Return an enumeration of names of attributes existing within this
* attribute.
*/
@Override
public Enumeration getAttributeNames() {
Vector elements = new Vector<>();
elements.addElement(DN_NAME);
return (elements.elements());
}
/**
* Return the name of this attribute.
*/
@Override
public String getName() {
return (NAME);
}
}
CertificateIssuerUniqueIdentity.java 0000664 0000000 0000000 00000013215 14565430767 0034226 0 ustar 00root root 0000000 0000000 jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.x509;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.Vector;
import org.mozilla.jss.netscape.security.util.DerInputStream;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
/**
* This class defines the subject/issuer unique identity attribute
* for the Certificate.
*
* @author Amit Kapoor
* @author Hemma Prafullchandra
* @version 1.6
* @see CertAttrSet
*/
public class CertificateIssuerUniqueIdentity implements CertAttrSet {
private UniqueIdentity id;
/**
* Identifier for this attribute, to be used with the
* get, set, delete methods of Certificate, x509 type.
*/
public static final String IDENT = "x509.info.issuerID";
/**
* Sub attributes name for this CertAttrSet.
*/
public static final String NAME = "issuerID";
public static final String ID = "id";
/**
* Default constructor for the certificate attribute.
*
* @param id the UniqueIdentity
*/
public CertificateIssuerUniqueIdentity(UniqueIdentity id) {
this.id = id;
}
/**
* Create the object, decoding the values from the passed DER stream.
*
* @param in the DerInputStream to read the UniqueIdentity from.
* @exception IOException on decoding errors.
*/
public CertificateIssuerUniqueIdentity(DerInputStream in)
throws IOException {
id = new UniqueIdentity(in);
}
/**
* Create the object, decoding the values from the passed stream.
*
* @param in the InputStream to read the UniqueIdentity from.
* @exception IOException on decoding errors.
*/
public CertificateIssuerUniqueIdentity(InputStream in)
throws IOException {
DerValue val = new DerValue(in);
id = new UniqueIdentity(val);
}
/**
* Create the object, decoding the values from the passed DER value.
*
* @param val the DerValue to read the UniqueIdentity from.
* @exception IOException on decoding errors.
*/
public CertificateIssuerUniqueIdentity(DerValue val)
throws IOException {
id = new UniqueIdentity(val);
}
/**
* Return the identity as user readable string.
*/
@Override
public String toString() {
if (id == null)
return "";
return (id.toString());
}
/**
* Decode the identity in DER form from the stream.
*
* @param in the InputStream to unmarshal the contents from.
* @exception IOException on errors.
*/
@Override
public void decode(InputStream in) throws IOException {
DerValue val = new DerValue(in);
id = new UniqueIdentity(val);
}
/**
* Encode the identity in DER form to the stream.
*
* @param out the DerOutputStream to marshal the contents to.
* @exception IOException on errors.
*/
@Override
public void encode(OutputStream out) throws IOException {
DerOutputStream tmp = new DerOutputStream();
id.encode(tmp, DerValue.createTag(DerValue.TAG_CONTEXT, false, (byte) 1));
out.write(tmp.toByteArray());
}
/**
* Set the attribute value.
*/
@Override
public void set(String name, Object obj) throws IOException {
if (!(obj instanceof UniqueIdentity)) {
throw new IOException("Attribute must be of type UniqueIdentity.");
}
if (name.equalsIgnoreCase(ID)) {
id = (UniqueIdentity) obj;
} else {
throw new IOException("Attribute name not recognized by " +
"CertAttrSet: CertificateIssuerUniqueIdentity.");
}
}
/**
* Get the attribute value.
*/
@Override
public Object get(String name) throws IOException {
if (name.equalsIgnoreCase(ID)) {
return (id);
} else {
throw new IOException("Attribute name not recognized by " +
"CertAttrSet: CertificateIssuerUniqueIdentity.");
}
}
/**
* Delete the attribute value.
*/
@Override
public void delete(String name) throws IOException {
if (name.equalsIgnoreCase(ID)) {
id = null;
} else {
throw new IOException("Attribute name not recognized by " +
"CertAttrSet: CertificateIssuerUniqueIdentity.");
}
}
/**
* Return an enumeration of names of attributes existing within this
* attribute.
*/
@Override
public Enumeration getAttributeNames() {
Vector elements = new Vector<>();
elements.addElement(ID);
return (elements.elements());
}
/**
* Return the name of this attribute.
*/
@Override
public String getName() {
return (NAME);
}
}
CertificatePoliciesExtension.java 0000664 0000000 0000000 00000027516 14565430767 0033530 0 ustar 00root root 0000000 0000000 jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.x509;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Array;
import java.util.Arrays;
import java.util.Collections;
import java.util.Enumeration;
import java.util.Vector;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
import org.mozilla.jss.netscape.security.util.ObjectIdentifier;
import org.mozilla.jss.netscape.security.util.Utils;
/**
* This class defines the Certificate Policies Extension.
*
*
* The certificate policies extension conatins a sequence of policy information terms, each of which consists of an
* object identifier (OID) and optional qualifiers. These policy information terms indicate the policy under which the
* certificate has been issued and the purposes for which the certificate may be used. Aplications with specific policy
* requirements are expected to have a list of those policies which they will accept and to compare the policy OIDs in
* the certificate to that list. If this extension is critical, the path validation software must be able to interpret
* this extension, or must reject the certificate.
*
*
* CertificatePolicies ::= SEQUENECE OF PolicyInformation
*
*
* @author Christine Ho
* @see Extension
* @see CertAttrSet
*/
public class CertificatePoliciesExtension extends Extension
implements CertAttrSet {
/**
*
*/
private static final long serialVersionUID = -3729294064061837367L;
/**
* Identifier for this attribute, to be used with the
* get, set, delete methods of Certificate, x509 type.
*/
public static final String IDENT = "x509.info.extensions.CertificatePolicies";
/**
* Attribute names.
*/
public static final String NAME = "CertificatePolicies";
public static final String INFOS = "infos";
// Private data members
private Vector mInfos;
// Encode this extension value
private void encodeThis() throws IOException {
try (DerOutputStream os = new DerOutputStream();) {
DerOutputStream tmp = new DerOutputStream();
for (int i = 0; i < mInfos.size(); i++) {
mInfos.elementAt(i).encode(tmp);
}
os.write(DerValue.tag_Sequence, tmp);
extensionValue = os.toByteArray();
}
}
public CertificatePoliciesExtension(boolean critical, Vector infos) throws IOException {
this.mInfos = infos;
this.extensionId = PKIXExtensions.CertificatePolicies_Id;
this.critical = critical;
encodeThis();
}
/**
* Create a CertificatePolicies with the Vector of CertificatePolicyInfo.
*
* @param infos the Vector of CertificatePolicyInfo.
*/
public CertificatePoliciesExtension(Vector infos) throws IOException {
this.mInfos = infos;
this.extensionId = PKIXExtensions.CertificatePolicies_Id;
this.critical = false;
encodeThis();
}
/**
* Create a default CertificatePoliciesExtension.
*/
public CertificatePoliciesExtension() {
this.extensionId = PKIXExtensions.CertificatePolicies_Id;
critical = false;
mInfos = new Vector<>(1, 1);
}
/**
* Create the extension from the passed DER encoded value.
*
* @param critical true if the extension is to be treated as critical.
* @param value Array of DER encoded bytes of the actual value.
* @exception IOException on error.
*/
public CertificatePoliciesExtension(Boolean critical, Object value)
throws IOException {
this.extensionId = PKIXExtensions.CertificatePolicies_Id;
this.critical = critical.booleanValue();
int len = Array.getLength(value);
byte[] extValue = new byte[len];
for (int i = 0; i < len; i++) {
extValue[i] = Array.getByte(value, i);
}
this.extensionValue = extValue;
DerValue val = new DerValue(extValue);
if (val.tag != DerValue.tag_Sequence) {
throw new IOException("Invalid encoding for " +
"CertificatePoliciesExtension.");
}
mInfos = new Vector<>(1, 1);
while (val.data.available() != 0) {
DerValue seq = val.data.getDerValue();
CertificatePolicyInfo info = new CertificatePolicyInfo(seq);
mInfos.addElement(info);
}
}
/**
* Returns a printable representation of the policy extension.
*/
@Override
public String toString() {
if (mInfos == null)
return "";
String s = super.toString() + "Certificate Policies [\n"
+ mInfos.toString() + "]\n";
return (s);
}
/**
* Write the extension to the OutputStream.
*
* @param out the OutputStream to write the extension to.
* @exception IOException on encoding errors.
*/
@Override
public void encode(OutputStream out) throws IOException {
DerOutputStream tmp = new DerOutputStream();
if (extensionValue == null) {
extensionId = PKIXExtensions.CertificatePolicies_Id;
critical = false;
encodeThis();
}
super.encode(tmp);
out.write(tmp.toByteArray());
}
/**
* Decode the extension from the InputStream.
*
* @param in the InputStream to unmarshal the contents from.
* @exception IOException on decoding or validity errors.
*/
@Override
public void decode(InputStream in) throws IOException {
throw new IOException("Method not to be called directly.");
}
/**
* Set the attribute value.
*/
@Override
@SuppressWarnings("unchecked")
public void set(String name, Object obj) throws IOException {
clearValue();
if (name.equalsIgnoreCase(INFOS)) {
if (!(obj instanceof Vector)) {
throw new IOException("Attribute value should be of" +
" type Vector.");
}
mInfos = (Vector) obj;
} else {
throw new IOException("Attribute name not recognized by " +
"CertAttrSet:CertificatePoliciesExtension.");
}
}
/**
* Get the attribute value.
*/
@Override
public Object get(String name) throws IOException {
if (name.equalsIgnoreCase(INFOS)) {
return (mInfos);
} else {
throw new IOException("Attribute name not recognized by " +
"CertAttrSet:CertificatePoliciesExtension.");
}
}
/**
* Delete the attribute value.
*/
@Override
public void delete(String name) throws IOException {
if (name.equalsIgnoreCase(INFOS)) {
mInfos = null;
} else {
throw new IOException("Attribute name not recognized by " +
"CertAttrSet:CertificatePoliciesExtension.");
}
}
/**
* Return an enumeration of attributes existing within this
* attribute.
*/
public Enumeration> getAttributes() {
Vector> elements = new Vector<>();
elements.addElement(mInfos);
return (elements.elements());
}
private static final String[] NAMES = { INFOS };
@Override
public Enumeration getAttributeNames() {
// TODO Auto-generated method stub
return Collections.enumeration(Arrays.asList(NAMES));
}
/**
* Return the name of this attribute.
*/
@Override
public String getName() {
return (NAME);
}
public static void main(String args[]) {
/**
* From ASN.1 dump
*
* 0 30 133: SEQUENCE {
* 3 30 45: . SEQUENCE {
* 5 06 3: . . OBJECT IDENTIFIER '1 2 3 5'
* 10 30 38: . . SEQUENCE {
* 12 30 36: . . . SEQUENCE {
* 14 06 8: . . . . OBJECT IDENTIFIER cps (1 3 6 1 5 5 7 2 1)
* : . . . . . (PKIX policy qualifier)
* 24 16 24: . . . . IA5String 'http://home.netscape.com'
* : . . . . }
* : . . . }
* : . . }
* 50 30 84: . SEQUENCE {
* 52 06 2: . . OBJECT IDENTIFIER '2 3 5'
* 56 30 78: . . SEQUENCE {
* 58 30 36: . . . SEQUENCE {
* 60 06 8: . . . . OBJECT IDENTIFIER cps (1 3 6 1 5 5 7 2 1)
* : . . . . . (PKIX policy qualifier)
* 70 16 24: . . . . IA5String 'http://home.netscape.com'
* : . . . . }
* 96 30 38: . . . SEQUENCE {
* 98 06 8: . . . . OBJECT IDENTIFIER unotice (1 3 6 1 5 5 7 2 2)
* : . . . . . (PKIX policy qualifier)
* 108 30 26: . . . . SEQUENCE {
* 110 30 16: . . . . . SEQUENCE {
* 112 1E 8: . . . . . . BMPString (1993) '_..o.r.g'
* 122 02 1: . . . . . . INTEGER 1
* 125 02 1: . . . . . . INTEGER 2
* : . . . . . . }
* 128 1E 6: . . . . . BMPString (1993) '_..d.t'
* : . . . . . }
* : . . . . }
* : . . . }
* : . . }
* : . }
**/
CertificatePolicyId plcyId0 = new CertificatePolicyId(
new ObjectIdentifier("1.2.3.5")
);
PolicyQualifiers qualifiers0 = new PolicyQualifiers();
CPSuri cpsQualifier0 = new CPSuri("http://home.netscape.com");
PolicyQualifierInfo qualifierInfo0 = new PolicyQualifierInfo(
PolicyQualifierInfo.QT_CPS,
cpsQualifier0
);
qualifiers0.add(qualifierInfo0);
CertificatePolicyInfo info0 = new CertificatePolicyInfo(
plcyId0, qualifiers0);
CertificatePolicyId plcyId1 = new CertificatePolicyId(
new ObjectIdentifier("2.3.5")
);
PolicyQualifiers qualifiers1 = new PolicyQualifiers();
DisplayText org1 = new DisplayText(DisplayText.tag_BMPString,
"org");
int nums[] = { 1, 2 };
NoticeReference nr1 = new NoticeReference(org1, nums);
DisplayText dt1 = new DisplayText(DisplayText.tag_BMPString,
"dt");
UserNotice userNotice1 = new UserNotice(nr1, dt1);
PolicyQualifierInfo qualifierInfo1 = new PolicyQualifierInfo(
PolicyQualifierInfo.QT_UNOTICE,
userNotice1
);
qualifiers1.add(qualifierInfo0);
qualifiers1.add(qualifierInfo1);
CertificatePolicyInfo info1 = new CertificatePolicyInfo(
plcyId1, qualifiers1);
Vector infos = new Vector<>();
infos.addElement(info0);
infos.addElement(info1);
try {
CertificatePoliciesExtension ext =
new CertificatePoliciesExtension(infos);
// BASE64 encode the whole thing and write it to stdout
System.out.println(Utils.base64encode(ext.getExtensionValue(), true));
} catch (IOException e) {
System.out.println(e.toString());
}
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509/CertificatePolicyId.java 0000664 0000000 0000000 00000004764 14565430767 0031657 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.x509;
import java.io.IOException;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
import org.mozilla.jss.netscape.security.util.ObjectIdentifier;
/**
* Represent the CertificatePolicyId ASN.1 object.
*
* @author Amit Kapoor
* @author Hemma Prafullchandra
* @version 1.5
*/
public class CertificatePolicyId implements java.io.Serializable {
/**
*
*/
private static final long serialVersionUID = -2376810529862707757L;
private ObjectIdentifier id;
/**
* Create a CertificatePolicyId with the ObjectIdentifier.
*
* @param id the ObjectIdentifier for the policy id.
*/
public CertificatePolicyId(ObjectIdentifier id) {
this.id = id;
}
/**
* Create the object from its Der encoded value.
*
* @param val the DER encoded value for the same.
*/
public CertificatePolicyId(DerValue val) throws IOException {
this.id = val.getOID();
}
/**
* Return the value of the CertificatePolicyId as an ObjectIdentifier.
*/
public ObjectIdentifier getIdentifier() {
return (id);
}
/**
* Returns a printable representation of the CertificatePolicyId.
*/
@Override
public String toString() {
String s = "CertificatePolicyId: ["
+ id.toString()
+ "]\n";
return (s);
}
/**
* Write the CertificatePolicyId to the DerOutputStream.
*
* @param out the DerOutputStream to write the object to.
* @exception IOException on errors.
*/
public void encode(DerOutputStream out) throws IOException {
out.putOID(id);
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509/CertificatePolicyInfo.java 0000664 0000000 0000000 00000007066 14565430767 0032214 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.x509;
import java.io.IOException;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
/**
* Represent the CertificatePolicyInformation ASN.1 object.
*
* @author Christine Ho
*/
public class CertificatePolicyInfo implements java.io.Serializable {
/**
*
*/
private static final long serialVersionUID = -8516006396099280477L;
private CertificatePolicyId mPolicyIdentifier;
private PolicyQualifiers mPolicyQualifiers;
/**
* Create a CertificatePolicyInfo with the passed CertificatePolicyId's.
*
* @param id the CertificatePolicyId.
*/
public CertificatePolicyInfo(CertificatePolicyId id) {
this.mPolicyIdentifier = id;
this.mPolicyQualifiers = null;
}
public CertificatePolicyInfo(CertificatePolicyId id, PolicyQualifiers qualifiers) {
this.mPolicyIdentifier = id;
this.mPolicyQualifiers = qualifiers;
}
/**
* Create the CertificatePolicyInfo from the DER encoded value.
*
* @param val the DER encoded value of the same.
*/
public CertificatePolicyInfo(DerValue val) throws IOException {
if (val.tag != DerValue.tag_Sequence) {
throw new IOException("Invalid encoding for CertificatePolicyInfo");
}
mPolicyIdentifier = new CertificatePolicyId(val.data.getDerValue());
// The specification is not clear on whether qualifier is
// optional or not. GTE CyberTrust Root certificate has
// no qualifier.
if (val.data.available() == 0) {
mPolicyQualifiers = null;
} else {
mPolicyQualifiers = new PolicyQualifiers(val.data.getDerValue());
}
}
/**
* return the policy identifier of the policy info
*/
public CertificatePolicyId getPolicyIdentifier() {
return (mPolicyIdentifier);
}
public PolicyQualifiers getPolicyQualifiers() {
return mPolicyQualifiers;
}
/**
* Returns a printable representation of the CertificatePolicyId.
*/
@Override
public String toString() {
String s = "CertificatePolicyInfo: [\n"
+ "PolicyIdentifier:" + mPolicyIdentifier.toString()
+ "]\n";
return (s);
}
/**
* Write the CertificatePolicyInfo to the DerOutputStream.
*
* @param out the DerOutputStream to write the object to.
* @exception IOException on errors.
*/
public void encode(DerOutputStream out) throws IOException {
DerOutputStream tmp = new DerOutputStream();
mPolicyIdentifier.encode(tmp);
if (mPolicyQualifiers != null) {
mPolicyQualifiers.encode(tmp);
}
out.write(DerValue.tag_Sequence, tmp);
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509/CertificatePolicyMap.java 0000664 0000000 0000000 00000006334 14565430767 0032033 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.x509;
import java.io.IOException;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
/**
* Represent the CertificatePolicyMap ASN.1 object.
*
* @author Amit Kapoor
* @author Hemma Prafullchandra
* @version 1.5
*/
public class CertificatePolicyMap {
private CertificatePolicyId issuerDomain;
private CertificatePolicyId subjectDomain;
/**
* Create a CertificatePolicyMap with the passed CertificatePolicyId's.
*
* @param issuer the CertificatePolicyId for the issuer CA.
* @param subject the CertificatePolicyId for the subject CA.
*/
public CertificatePolicyMap(CertificatePolicyId issuer,
CertificatePolicyId subject) {
this.issuerDomain = issuer;
this.subjectDomain = subject;
}
/**
* Create the CertificatePolicyMap from the DER encoded value.
*
* @param val the DER encoded value of the same.
*/
public CertificatePolicyMap(DerValue val) throws IOException {
if (val.tag != DerValue.tag_Sequence) {
throw new IOException("Invalid encoding for CertificatePolicyMap");
}
issuerDomain = new CertificatePolicyId(val.data.getDerValue());
subjectDomain = new CertificatePolicyId(val.data.getDerValue());
}
/**
* Return the issuer CA part of the policy map.
*/
public CertificatePolicyId getIssuerIdentifier() {
return (issuerDomain);
}
/**
* Return the subject CA part of the policy map.
*/
public CertificatePolicyId getSubjectIdentifier() {
return (subjectDomain);
}
/**
* Returns a printable representation of the CertificatePolicyId.
*/
@Override
public String toString() {
String s = "CertificatePolicyMap: [\n"
+ "IssuerDomain:" + issuerDomain.toString()
+ "SubjectDomain:" + subjectDomain.toString()
+ "]\n";
return (s);
}
/**
* Write the CertificatePolicyMap to the DerOutputStream.
*
* @param out the DerOutputStream to write the object to.
* @exception IOException on errors.
*/
public void encode(DerOutputStream out) throws IOException {
DerOutputStream tmp = new DerOutputStream();
issuerDomain.encode(tmp);
subjectDomain.encode(tmp);
out.write(DerValue.tag_Sequence, tmp);
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509/CertificatePolicySet.java 0000664 0000000 0000000 00000005127 14565430767 0032050 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.x509;
import java.io.IOException;
import java.util.Vector;
import org.mozilla.jss.netscape.security.util.DerInputStream;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
/**
* This class defines the certificate policy set ASN.1 object.
*
* @author Amit Kapoor
* @author Hemma Prafullchandra
* @version 1.4
*/
public class CertificatePolicySet {
private Vector ids;
/**
* The default constructor for this class.
*
* @param ids the sequence of CertificatePolicyId's.
*/
public CertificatePolicySet(Vector ids) {
this.ids = ids;
}
/**
* Create the object from the DerValue.
*
* @param in the passed DerInputStream.
* @exception IOException on decoding errors.
*/
public CertificatePolicySet(DerInputStream in) throws IOException {
ids = new Vector<>(1, 1);
DerValue[] seq = in.getSequence(5);
for (int i = 0; i < seq.length; i++) {
CertificatePolicyId id = new CertificatePolicyId(seq[i]);
ids.addElement(id);
}
}
/**
* Return printable form of the object.
*/
@Override
public String toString() {
String s = "CertificatePolicySet:[\n"
+ ids.toString()
+ "]\n";
return (s);
}
/**
* Encode the policy set to the output stream.
*
* @param out the DerOutputStream to encode the data to.
*/
public void encode(DerOutputStream out) throws IOException {
DerOutputStream tmp = new DerOutputStream();
for (int i = 0; i < ids.size(); i++) {
ids.elementAt(i).encode(tmp);
}
out.write(DerValue.tag_Sequence, tmp);
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509/CertificateSerialNumber.java 0000664 0000000 0000000 00000013462 14565430767 0032526 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.x509;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigInteger;
import java.util.Enumeration;
import java.util.Vector;
import org.mozilla.jss.netscape.security.util.DerInputStream;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
/**
* This class defines the SerialNumber attribute for the Certificate.
*
* @author Amit Kapoor
* @author Hemma Prafullchandra
* @version 1.6
* @see CertAttrSet
*/
public class CertificateSerialNumber implements CertAttrSet {
/**
* Identifier for this attribute, to be used with the
* get, set, delete methods of Certificate, x509 type.
*/
public static final String IDENT = "x509.info.serialNumber";
/**
* Sub attributes name for this CertAttrSet.
*/
public static final String NAME = "serialNumber";
public static final String NUMBER = "number";
private SerialNumber serial;
/**
* Default constructor for the certificate attribute.
*
* @param num the serial number for the certificate.
*/
public CertificateSerialNumber(BigInteger num) {
this.serial = new SerialNumber(num);
}
/**
* Default constructor for the certificate attribute.
*
* @param num the serial number for the certificate.
*/
public CertificateSerialNumber(int num) {
this.serial = new SerialNumber(num);
}
/**
* Create the object, decoding the values from the passed DER stream.
*
* @param in the DerInputStream to read the serial number from.
* @exception IOException on decoding errors.
*/
public CertificateSerialNumber(DerInputStream in) throws IOException {
serial = new SerialNumber(in);
}
/**
* Create the object, decoding the values from the passed stream.
*
* @param in the InputStream to read the serial number from.
* @exception IOException on decoding errors.
*/
public CertificateSerialNumber(InputStream in) throws IOException {
serial = new SerialNumber(in);
}
/**
* Create the object, decoding the values from the passed DerValue.
*
* @param val the DER encoded value.
* @exception IOException on decoding errors.
*/
public CertificateSerialNumber(DerValue val) throws IOException {
serial = new SerialNumber(val);
}
/**
* Return the serial number as user readable string.
*/
@Override
public String toString() {
if (serial == null)
return "";
return (serial.toString());
}
/**
* Encode the serial number in DER form to the stream.
*
* @param out the DerOutputStream to marshal the contents to.
* @exception IOException on errors.
*/
@Override
public void encode(OutputStream out) throws IOException {
DerOutputStream tmp = new DerOutputStream();
serial.encode(tmp);
out.write(tmp.toByteArray());
}
/**
* Decode the serial number in DER form from the stream.
*
* @param in the InputStream to marshal the contents from.
* @exception IOException on errors.
*/
@Override
public void decode(InputStream in) throws IOException {
DerValue derVal = new DerValue(in);
serial = new SerialNumber(derVal);
}
/**
* Set the attribute value.
*/
@Override
public void set(String name, Object obj) throws IOException {
if (!(obj instanceof SerialNumber)) {
throw new IOException("Attribute must be of type SerialNumber.");
}
if (name.equalsIgnoreCase(NUMBER)) {
serial = (SerialNumber) obj;
} else {
throw new IOException("Attribute name not recognized by " +
"CertAttrSet:CertificateSerialNumber.");
}
}
/**
* Get the attribute value.
*/
@Override
public Object get(String name) throws IOException {
if (name.equalsIgnoreCase(NUMBER)) {
return (serial);
} else {
throw new IOException("Attribute name not recognized by " +
"CertAttrSet:CertificateSerialNumber.");
}
}
/**
* Delete the attribute value.
*/
@Override
public void delete(String name) throws IOException {
if (name.equalsIgnoreCase(NUMBER)) {
serial = null;
} else {
throw new IOException("Attribute name not recognized by " +
"CertAttrSet:CertificateSerialNumber.");
}
}
/**
* Return an enumeration of names of attributes existing within this
* attribute.
*/
@Override
public Enumeration getAttributeNames() {
Vector elements = new Vector<>();
elements.addElement(NUMBER);
return (elements.elements());
}
/**
* Return the name of this attribute.
*/
@Override
public String getName() {
return (NAME);
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509/CertificateSubjectName.java 0000664 0000000 0000000 00000014377 14565430767 0032344 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.x509;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.Enumeration;
import java.util.Vector;
import org.mozilla.jss.netscape.security.util.DerInputStream;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
/**
* This class defines the X500Name attribute for the Certificate.
*
* @author Amit Kapoor
* @author Hemma Prafullchandra
* @version 1.6
* @see CertAttrSet
*/
public class CertificateSubjectName implements CertAttrSet, Serializable {
/**
*
*/
private static final long serialVersionUID = 503643453152834350L;
/**
* Identifier for this attribute, to be used with the
* get, set, delete methods of Certificate, x509 type.
*/
public static final String IDENT = "x509.info.subject";
/**
* Sub attributes name for this CertAttrSet.
*/
public static final String NAME = "subject";
public static final String DN_NAME = "dname";
// Private data member
private X500Name dnName;
/**
* Default constructor for the certificate attribute.
*
* @param name the X500Name
*/
public CertificateSubjectName(X500Name name) {
this.dnName = name;
}
/**
* Create the object, decoding the values from the passed DER stream.
*
* @param in the DerInputStream to read the X500Name from.
* @exception IOException on decoding errors.
*/
public CertificateSubjectName(DerInputStream in) throws IOException {
dnName = new X500Name(in);
}
/**
* Create the object, decoding the values from the passed stream.
*
* @param in the InputStream to read the X500Name from.
* @exception IOException on decoding errors.
*/
public CertificateSubjectName(InputStream in) throws IOException {
DerValue derVal = new DerValue(in);
dnName = new X500Name(derVal);
}
/**
* Return the name as user readable string.
*/
@Override
public String toString() {
if (dnName == null)
return "";
return (dnName.toString());
}
private void writeObject(ObjectOutputStream stream) throws IOException {
encode(stream);
}
private void readObject(ObjectInputStream stream) throws IOException {
decodeEx(stream);
}
/**
* Encode the name in DER form to the stream.
*
* @param out the DerOutputStream to marshal the contents to.
* @exception IOException on errors.
*/
@Override
public void encode(OutputStream out) throws IOException {
DerOutputStream tmp = new DerOutputStream();
dnName.encode(tmp);
out.write(tmp.toByteArray());
}
/**
* Decode the name in DER form from the stream.
*
* @param in the InputStream to marshal the contents from.
* @exception IOException on errors.
*/
public void decodeEx(InputStream in) throws IOException {
DerValue derVal = new DerValue(in);
// dnName = new X500Name(derVal);
dnName = new X500Name(derVal.toByteArray());
}
/**
* Decode the name in DER form from the stream.
*
* @param in the InputStream to marshal the contents from.
* @exception IOException on errors.
*/
@Override
public void decode(InputStream in) throws IOException {
DerValue derVal = new DerValue(in);
dnName = new X500Name(derVal);
}
/**
* Set the attribute value.
*/
@Override
public void set(String name, Object obj) throws IOException {
if (!(obj instanceof X500Name)) {
throw new IOException("Attribute must be of type X500Name.");
}
if (name.equalsIgnoreCase(DN_NAME)) {
this.dnName = (X500Name) obj;
} else {
throw new IOException("Attribute name not recognized by " +
"CertAttrSet:CertificateSubjectName.");
}
}
/**
* Get the attribute value.
*/
@Override
public Object get(String name) throws IOException {
if (name.equalsIgnoreCase(DN_NAME)) {
return (dnName);
} else {
throw new IOException("Attribute name not recognized by " +
"CertAttrSet:CertificateSubjectName.");
}
}
/**
* Get underlying X500Name value.
*
* Where the type is known to be CertificateSubjectName, use
* this method instead of 'get' to avoid casts and exceptions.
*/
public X500Name getX500Name() {
return dnName;
}
/**
* Delete the attribute value.
*/
@Override
public void delete(String name) throws IOException {
if (name.equalsIgnoreCase(DN_NAME)) {
dnName = null;
} else {
throw new IOException("Attribute name not recognized by " +
"CertAttrSet:CertificateSubjectName.");
}
}
/**
* Return an enumeration of names of attributes existing within this
* attribute.
*/
@Override
public Enumeration getAttributeNames() {
Vector elements = new Vector<>();
elements.addElement(DN_NAME);
return (elements.elements());
}
/**
* Return the name of this attribute.
*/
@Override
public String getName() {
return (NAME);
}
}
CertificateSubjectUniqueIdentity.java 0000664 0000000 0000000 00000013227 14565430767 0034356 0 ustar 00root root 0000000 0000000 jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.x509;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.Vector;
import org.mozilla.jss.netscape.security.util.DerInputStream;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
/**
* This class defines the subject/issuer unique identity attribute
* for the Certificate.
*
* @author Amit Kapoor
* @author Hemma Prafullchandra
* @version 1.6
* @see CertAttrSet
*/
public class CertificateSubjectUniqueIdentity implements CertAttrSet {
/**
* Identifier for this attribute, to be used with the
* get, set, delete methods of Certificate, x509 type.
*/
public static final String IDENT = "x509.info.subjectID";
/**
* Sub attributes name for this CertAttrSet.
*/
public static final String NAME = "subjectID";
public static final String ID = "id";
private UniqueIdentity id;
/**
* Default constructor for the certificate attribute.
*
* @param id the UniqueIdentity
*/
public CertificateSubjectUniqueIdentity(UniqueIdentity id) {
this.id = id;
}
/**
* Create the object, decoding the values from the passed DER stream.
*
* @param in the DerInputStream to read the UniqueIdentity from.
* @exception IOException on decoding errors.
*/
public CertificateSubjectUniqueIdentity(DerInputStream in)
throws IOException {
id = new UniqueIdentity(in);
}
/**
* Create the object, decoding the values from the passed stream.
*
* @param in the InputStream to read the UniqueIdentity from.
* @exception IOException on decoding errors.
*/
public CertificateSubjectUniqueIdentity(InputStream in)
throws IOException {
DerValue val = new DerValue(in);
id = new UniqueIdentity(val);
}
/**
* Create the object, decoding the values from the passed DER value.
*
* @param val the DerValue to read the UniqueIdentity from.
* @exception IOException on decoding errors.
*/
public CertificateSubjectUniqueIdentity(DerValue val)
throws IOException {
id = new UniqueIdentity(val);
}
/**
* Return the identity as user readable string.
*/
@Override
public String toString() {
if (id == null)
return "";
return (id.toString());
}
/**
* Decode the identity in DER form from the stream.
*
* @param in the InputStream to unmarshal the contents from.
* @exception IOException on errors.
*/
@Override
public void decode(InputStream in) throws IOException {
DerValue val = new DerValue(in);
id = new UniqueIdentity(val);
}
/**
* Encode the identity in DER form to the stream.
*
* @param out the DerOutputStream to marshal the contents to.
* @exception IOException on errors.
*/
@Override
public void encode(OutputStream out) throws IOException {
DerOutputStream tmp = new DerOutputStream();
id.encode(tmp, DerValue.createTag(DerValue.TAG_CONTEXT, false, (byte) 2));
out.write(tmp.toByteArray());
}
/**
* Set the attribute value.
*/
@Override
public void set(String name, Object obj) throws IOException {
if (!(obj instanceof UniqueIdentity)) {
throw new IOException("Attribute must be of type UniqueIdentity.");
}
if (name.equalsIgnoreCase(ID)) {
id = (UniqueIdentity) obj;
} else {
throw new IOException("Attribute name not recognized by " +
"CertAttrSet: CertificateSubjectUniqueIdentity.");
}
}
/**
* Get the attribute value.
*/
@Override
public Object get(String name) throws IOException {
if (name.equalsIgnoreCase(ID)) {
return (id);
} else {
throw new IOException("Attribute name not recognized by " +
"CertAttrSet: CertificateSubjectUniqueIdentity.");
}
}
/**
* Delete the attribute value.
*/
@Override
public void delete(String name) throws IOException {
if (name.equalsIgnoreCase(ID)) {
id = null;
} else {
throw new IOException("Attribute name not recognized by " +
"CertAttrSet: CertificateSubjectUniqueIdentity.");
}
}
/**
* Return an enumeration of names of attributes existing within this
* attribute.
*/
@Override
public Enumeration getAttributeNames() {
Vector elements = new Vector<>();
elements.addElement(ID);
return (elements.elements());
}
/**
* Return the name of this attribute.
*/
@Override
public String getName() {
return (NAME);
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509/CertificateValidity.java 0000664 0000000 0000000 00000024434 14565430767 0031724 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.x509;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateNotYetValidException;
import java.util.Date;
import java.util.Enumeration;
import java.util.Vector;
import org.mozilla.jss.netscape.security.util.DerInputStream;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
/**
* This class defines the interval for which the certificate is valid.
*
* @author Amit Kapoor
* @author Hemma Prafullchandra
* @version 1.12
* @see CertAttrSet
*/
public class CertificateValidity implements CertAttrSet, Serializable {
private static final long serialVersionUID = 8277703278213804194L;
/**
* Identifier for this attribute, to be used with the
* get, set, delete methods of Certificate, x509 type.
*/
public static final String IDENT = "x509.info.validity";
/**
* Sub attributes name for this CertAttrSet.
*/
public static final String NAME = "validity";
public static final String NOT_BEFORE = "notBefore";
public static final String NOT_AFTER = "notAfter";
private static final long YR_2050 = 2524636800000L;
// Private data members
private Date notBefore;
private Date notAfter;
// Returns the first time the certificate is valid.
private Date getNotBefore() {
return (new Date(notBefore.getTime()));
}
// Returns the last time the certificate is valid.
private Date getNotAfter() {
return (new Date(notAfter.getTime()));
}
// Construct the class from the DerValue
private void construct(DerValue derVal) throws IOException {
if (derVal.tag != DerValue.tag_Sequence) {
throw new IOException("Invalid encoded CertificateValidity, " +
"starting sequence tag missing.");
}
// check if UTCTime encoded or GeneralizedTime
if (derVal.data.available() == 0)
throw new IOException("No data encoded for CertificateValidity");
DerInputStream derIn = new DerInputStream(derVal.toByteArray());
DerValue[] seq = derIn.getSequence(2);
if (seq.length != 2)
throw new IOException("Invalid encoding for CertificateValidity");
if (seq[0].tag == DerValue.tag_UtcTime) {
notBefore = derVal.data.getUTCTime();
} else if (seq[0].tag == DerValue.tag_GeneralizedTime) {
notBefore = derVal.data.getGeneralizedTime();
} else {
throw new IOException("Invalid encoding for CertificateValidity");
}
if (seq[1].tag == DerValue.tag_UtcTime) {
notAfter = derVal.data.getUTCTime();
} else if (seq[1].tag == DerValue.tag_GeneralizedTime) {
notAfter = derVal.data.getGeneralizedTime();
} else {
throw new IOException("Invalid encoding for CertificateValidity");
}
}
/**
* Default constructor for the class.
*/
public CertificateValidity() {
}
/**
* The default constructor for this class for the specified interval.
*
* @param notBefore the date and time before which the certificate
* is not valid.
* @param notAfter the date and time after which the certificate is
* not valid.
*/
public CertificateValidity(Date notBefore, Date notAfter) {
this.notBefore = notBefore;
this.notAfter = notAfter;
}
/**
* Create the object, decoding the values from the passed DER stream.
*
* @param in the DerInputStream to read the CertificateValidity from.
* @exception IOException on decoding errors.
*/
public CertificateValidity(DerInputStream in) throws IOException {
DerValue derVal = in.getDerValue();
construct(derVal);
}
/**
* Return the validity period as user readable string.
*/
@Override
public String toString() {
if (notBefore == null || notAfter == null)
return "";
return ("Validity: [From: " + notBefore.toString() +
",\n To: " + notAfter.toString() + "]");
}
/**
* Decode the CertificateValidity period from the InputStream.
*
* @param in the InputStream to unmarshal the contents from.
* @exception IOException on errors.
*/
@Override
public void decode(InputStream in) throws IOException {
DerValue derVal = new DerValue(in);
construct(derVal);
}
private void writeObject(ObjectOutputStream stream) throws IOException {
encode(stream);
}
private void readObject(ObjectInputStream stream) throws IOException {
decode(stream);
}
/**
* Encode the CertificateValidity period in DER form to the stream.
*
* @param out the OutputStream to marshal the contents to.
* @exception IOException on errors.
*/
@Override
public void encode(OutputStream out) throws IOException {
// in cases where default constructor is used check for
// null values
if (notBefore == null || notAfter == null) {
throw new IOException("CertAttrSet:CertificateValidity:" +
" null values to encode.\n");
}
try (DerOutputStream pair = new DerOutputStream();
DerOutputStream seq = new DerOutputStream()) {
if (notBefore.getTime() < YR_2050) {
pair.putUTCTime(notBefore);
} else
pair.putGeneralizedTime(notBefore);
if (notAfter.getTime() < YR_2050) {
pair.putUTCTime(notAfter);
} else {
pair.putGeneralizedTime(notAfter);
}
seq.write(DerValue.tag_Sequence, pair);
out.write(seq.toByteArray());
}
}
/**
* Set the attribute value.
*/
@Override
public void set(String name, Object obj) throws IOException {
if (!(obj instanceof Date)) {
throw new IOException("Attribute must be of type Date.");
}
if (name.equalsIgnoreCase(NOT_BEFORE)) {
notBefore = (Date) obj;
} else if (name.equalsIgnoreCase(NOT_AFTER)) {
notAfter = (Date) obj;
} else {
throw new IOException("Attribute name not recognized by " +
"CertAttrSet: CertificateValidity.");
}
}
/**
* Get the attribute value.
*/
@Override
public Object get(String name) throws IOException {
if (name.equalsIgnoreCase(NOT_BEFORE)) {
return (getNotBefore());
} else if (name.equalsIgnoreCase(NOT_AFTER)) {
return (getNotAfter());
} else {
throw new IOException("Attribute name not recognized by " +
"CertAttrSet: CertificateValidity.");
}
}
/**
* Delete the attribute value.
*/
@Override
public void delete(String name) throws IOException {
if (name.equalsIgnoreCase(NOT_BEFORE)) {
notBefore = null;
} else if (name.equalsIgnoreCase(NOT_AFTER)) {
notAfter = null;
} else {
throw new IOException("Attribute name not recognized by " +
"CertAttrSet: CertificateValidity.");
}
}
/**
* Return an enumeration of names of attributes existing within this
* attribute.
*/
@Override
public Enumeration getAttributeNames() {
Vector elements = new Vector<>();
elements.addElement(NOT_BEFORE);
elements.addElement(NOT_AFTER);
return (elements.elements());
}
/**
* Return the name of this attribute.
*/
@Override
public String getName() {
return (NAME);
}
/**
* Verify that the current time is within the validity period.
*
* @exception CertificateExpiredException if the certificate has expired.
* @exception CertificateNotYetValidException if the certificate is not
* yet valid.
*/
public void valid()
throws CertificateNotYetValidException, CertificateExpiredException {
Date now = new Date();
valid(now);
}
/**
* Verify that the passed time is within the validity period.
*
* @param now the Date against which to compare the validity
* period.
*
* @exception CertificateExpiredException if the certificate has expired
* with respect to the Date
supplied.
* @exception CertificateNotYetValidException if the certificate is not
* yet valid with respect to the Date
supplied.
*
*/
public void valid(Date now)
throws CertificateNotYetValidException, CertificateExpiredException {
/*
* we use the internal Dates rather than the passed in Date
* because someone could override the Date methods after()
* and before() to do something entirely different.
*/
if (notBefore.after(now)) {
throw new CertificateNotYetValidException("NotBefore: " +
notBefore.toString());
}
if (notAfter.before(now)) {
throw new CertificateExpiredException("NotAfter: " +
notAfter.toString());
}
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509/CertificateVersion.java 0000664 0000000 0000000 00000016540 14565430767 0031563 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.x509;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Enumeration;
import java.util.Vector;
import org.mozilla.jss.netscape.security.util.BigInt;
import org.mozilla.jss.netscape.security.util.DerInputStream;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
/**
* This class defines the version of the X509 Certificate.
*
* @author Amit Kapoor
* @author Hemma Prafullchandra
* @version 1.8
* @see CertAttrSet
*/
public class CertificateVersion implements CertAttrSet {
/**
* X509Certificate Version 1
*/
public static final int V1 = 0;
/**
* X509Certificate Version 2
*/
public static final int V2 = 1;
/**
* X509Certificate Version 3
*/
public static final int V3 = 2;
/**
* Identifier for this attribute, to be used with the
* get, set, delete methods of Certificate, x509 type.
*/
public static final String IDENT = "x509.info.version";
/**
* Sub attributes name for this CertAttrSet.
*/
public static final String NAME = "version";
public static final String VERSION = "number";
// Private data members
int version = V1;
// Returns the version number.
private int getVersion() {
return (version);
}
// Construct the class from the passed DerValue
private void construct(DerValue derVal) throws IOException {
if (derVal.isConstructed() && derVal.isContextSpecific()) {
derVal = derVal.data.getDerValue();
version = derVal.getInteger().toInt();
if (derVal.data.available() != 0) {
throw new IOException("X.509 version, bad format");
}
}
}
/**
* The default constructor for this class,
* sets the version to 0 (i.e. X.509 version 1).
*/
public CertificateVersion() {
version = V1;
}
/**
* The constructor for this class for the required version.
*
* @param version the version for the certificate.
* @exception IOException if the version is not valid.
*/
public CertificateVersion(int version) throws IOException {
// check that it is a valid version
if (version == V1 || version == V2 || version == V3)
this.version = version;
else {
throw new IOException("X.509 Certificate version " +
version + " not supported.\n");
}
}
/**
* Create the object, decoding the values from the passed DER stream.
*
* @param in the DerInputStream to read the CertificateVersion from.
* @exception IOException on decoding errors.
*/
public CertificateVersion(DerInputStream in) throws IOException {
version = V1;
DerValue derVal = in.getDerValue();
construct(derVal);
}
/**
* Create the object, decoding the values from the passed stream.
*
* @param in the InputStream to read the CertificateVersion from.
* @exception IOException on decoding errors.
*/
public CertificateVersion(InputStream in) throws IOException {
version = V1;
DerValue derVal = new DerValue(in);
construct(derVal);
}
/**
* Create the object, decoding the values from the passed DerValue.
*
* @param val the Der encoded value.
* @exception IOException on decoding errors.
*/
public CertificateVersion(DerValue val) throws IOException {
version = V1;
construct(val);
}
/**
* Return the version number of the certificate.
*/
@Override
public String toString() {
return ("Version: V" + (version + 1));
}
/**
* Encode the CertificateVersion period in DER form to the stream.
*
* @param out the OutputStream to marshal the contents to.
* @exception IOException on errors.
*/
@Override
public void encode(OutputStream out) throws IOException {
// Nothing for default
if (version == V1) {
return;
}
try (DerOutputStream tmp = new DerOutputStream();
DerOutputStream seq = new DerOutputStream()) {
tmp.putInteger(new BigInt(version));
seq.write(DerValue.createTag(DerValue.TAG_CONTEXT, true, (byte) 0),
tmp);
out.write(seq.toByteArray());
}
}
/**
* Decode the CertificateVersion period in DER form from the stream.
*
* @param in the InputStream to unmarshal the contents from.
* @exception IOException on errors.
*/
@Override
public void decode(InputStream in) throws IOException {
DerValue derVal = new DerValue(in);
construct(derVal);
}
/**
* Set the attribute value.
*/
@Override
public void set(String name, Object obj) throws IOException {
if (!(obj instanceof Integer)) {
throw new IOException("Attribute must be of type Integer.");
}
if (name.equalsIgnoreCase(VERSION)) {
version = ((Integer) obj).intValue();
} else {
throw new IOException("Attribute name not recognized by " +
"CertAttrSet: CertificateVersion.");
}
}
/**
* Get the attribute value.
*/
@Override
public Object get(String name) throws IOException {
if (name.equalsIgnoreCase(VERSION)) {
return (Integer.valueOf(getVersion()));
} else {
throw new IOException("Attribute name not recognized by " +
"CertAttrSet: CertificateVersion.");
}
}
/**
* Delete the attribute value.
*/
@Override
public void delete(String name) throws IOException {
if (name.equalsIgnoreCase(VERSION)) {
version = V1;
} else {
throw new IOException("Attribute name not recognized by " +
"CertAttrSet: CertificateVersion.");
}
}
/**
* Return an enumeration of names of attributes existing within this
* attribute.
*/
@Override
public Enumeration getAttributeNames() {
Vector elements = new Vector<>();
elements.addElement(VERSION);
return (elements.elements());
}
/**
* Return the name of this attribute.
*/
@Override
public String getName() {
return (NAME);
}
/**
* Compare versions.
*/
public int compare(int vers) {
return (version - vers);
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509/CertificateX509Key.java 0000664 0000000 0000000 00000013027 14565430767 0031251 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.x509;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;
import java.util.Enumeration;
import java.util.Vector;
import org.mozilla.jss.netscape.security.util.DerInputStream;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
/**
* This class defines the X509Key attribute for the Certificate.
*
* @author Amit Kapoor
* @author Hemma Prafullchandra
* @version 1.5
* @see CertAttrSet
*/
public class CertificateX509Key implements CertAttrSet, Serializable {
/**
*
*/
private static final long serialVersionUID = 6718749024328681131L;
/**
* Identifier for this attribute, to be used with the
* get, set, delete methods of Certificate, x509 type.
*/
public static final String IDENT = "x509.info.key";
/**
* Sub attributes name for this CertAttrSet.
*/
public static final String NAME = "key";
public static final String KEY = "value";
// Private data member
private X509Key key;
/**
* Default constructor for the certificate attribute.
*
* @param key the X509Key
*/
public CertificateX509Key(X509Key key) {
this.key = key;
}
/**
* Create the object, decoding the values from the passed DER stream.
*
* @param in the DerInputStream to read the X509Key from.
* @exception IOException on decoding errors.
*/
public CertificateX509Key(DerInputStream in) throws IOException {
DerValue val = in.getDerValue();
key = X509Key.parse(val);
}
/**
* Create the object, decoding the values from the passed stream.
*
* @param in the InputStream to read the X509Key from.
* @exception IOException on decoding errors.
*/
public CertificateX509Key(InputStream in) throws IOException {
DerValue val = new DerValue(in);
key = X509Key.parse(val);
}
/**
* Return the key as printable string.
*/
@Override
public String toString() {
if (key == null)
return "";
return (key.toString());
}
/**
* Decode the key in DER form from the stream.
*
* @param in the InputStream to unmarshal the contents from
* @exception IOException on decoding or validity errors.
*/
@Override
public void decode(InputStream in) throws IOException {
DerValue val = new DerValue(in);
key = X509Key.parse(val);
}
private void writeObject(ObjectOutputStream stream) throws IOException {
encode(stream);
}
private void readObject(ObjectInputStream stream) throws IOException {
decode(stream);
}
/**
* Encode the key in DER form to the stream.
*
* @param out the OutputStream to marshal the contents to.
* @exception IOException on errors.
*/
@Override
public void encode(OutputStream out) throws IOException {
DerOutputStream tmp = new DerOutputStream();
key.encode(tmp);
out.write(tmp.toByteArray());
}
/**
* Set the attribute value.
*/
@Override
public void set(String name, Object obj) throws IOException {
if (!(obj instanceof X509Key)) {
throw new IOException("Attribute must be of type X509Key.");
}
if (name.equalsIgnoreCase(KEY)) {
this.key = (X509Key) obj;
} else {
throw new IOException("Attribute name not recognized by " +
"CertAttrSet: CertificateX509Key.");
}
}
/**
* Get the attribute value.
*/
@Override
public Object get(String name) throws IOException {
if (name.equalsIgnoreCase(KEY)) {
return (key);
} else {
throw new IOException("Attribute name not recognized by " +
"CertAttrSet: CertificateX509Key.");
}
}
/**
* Delete the attribute value.
*/
@Override
public void delete(String name) throws IOException {
if (name.equalsIgnoreCase(KEY)) {
key = null;
} else {
throw new IOException("Attribute name not recognized by " +
"CertAttrSet: CertificateX509Key.");
}
}
/**
* Return an enumeration of names of attributes existing within this
* attribute.
*/
@Override
public Enumeration getAttributeNames() {
Vector elements = new Vector<>();
elements.addElement(KEY);
return (elements.elements());
}
/**
* Return the name of this attribute.
*/
@Override
public String getName() {
return (NAME);
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509/ChallengePassword.java 0000664 0000000 0000000 00000007776 14565430767 0031413 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.x509;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.cert.CertificateException;
import java.util.Enumeration;
import java.util.Vector;
import org.mozilla.jss.netscape.security.util.DerValue;
/**
* Class for handling the decoding of a SCEP Challenge Password
* object. Currently this class cannot be used for encoding
* thus some fo the methods are unimplemented
*/
public class ChallengePassword implements CertAttrSet {
public static final String NAME = "ChallengePassword";
public static final String PASSWORD = "password";
private String cpw;
/**
* Get the password marshalled in this object
*
* @return the challenge password
*/
@Override
public String toString() {
return cpw;
}
/**
* Create a ChallengePassword object
*
* @param stuff (must be of type byte[]) a DER-encoded by array following
* The ASN.1 template for ChallenegePassword specified in the SCEP
* documentation
* @throws IOException if the DER encoded byt array was malformed, or if it
* did not match the template
*/
public ChallengePassword(Object stuff)
throws IOException {
ByteArrayInputStream is = new ByteArrayInputStream((byte[]) stuff);
try {
decode(is);
} catch (Exception e) {
throw new IOException(e.getMessage());
}
}
/**
* Currently Unimplemented
*/
@Override
public void encode(OutputStream out)
throws CertificateException, IOException {
}
@Override
public void decode(InputStream in)
throws CertificateException, IOException {
DerValue derVal = new DerValue(in);
construct(derVal);
}
private void construct(DerValue derVal) throws IOException {
try {
cpw = derVal.getDirectoryString();
} catch (NullPointerException e) {
cpw = "";
}
}
/**
* Currently Unimplemented
*/
@Override
public void set(String name, Object obj)
throws CertificateException, IOException {
}
/**
* Get an attribute of this object.
*
* @param name the name of the attribute of this object to get. The only
* supported attribute is "password"
*/
@Override
public Object get(String name)
throws CertificateException, IOException {
if (name.equalsIgnoreCase(PASSWORD)) {
return cpw;
} else {
throw new IOException("Attribute name not recognized by " +
"CertAttrSet: ChallengePassword");
}
}
/**
* Currently Unimplemented
*/
@Override
public void delete(String name)
throws CertificateException, IOException {
}
/**
* @return an empty set of elements
*/
@Override
public Enumeration getAttributeNames() {
return (new Vector()).elements();
}
/**
* @return the String "ChallengePassword"
*/
@Override
public String getName() {
return NAME;
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509/DNSName.java 0000664 0000000 0000000 00000004725 14565430767 0027222 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.x509;
import java.io.IOException;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
/**
* This class implements the DNSName as required by the GeneralNames
* ASN.1 object.
*
* @author Amit Kapoor
* @author Hemma Prafullchandra
* @version 1.4
*/
public class DNSName implements GeneralNameInterface {
/**
*
*/
private static final long serialVersionUID = -2907649488092607056L;
private String name;
/**
* Create the DNSName object from the passed encoded Der value.
*
* @param derValue the encoded DER DNSName.
* @exception IOException on error.
*/
public DNSName(DerValue derValue) throws IOException {
name = derValue.getIA5String();
}
/**
* Create the DNSName object with the specified name.
*
* @param name the DNSName.
*/
public DNSName(String name) {
this.name = name;
}
/**
* Return the type of the GeneralName.
*/
@Override
public int getType() {
return (GeneralNameInterface.NAME_DNS);
}
/**
* Encode the DNS name into the DerOutputStream.
*
* @param out the DER stream to encode the DNSName to.
* @exception IOException on encoding errors.
*/
@Override
public void encode(DerOutputStream out) throws IOException {
out.putIA5String(name);
}
/**
* Convert the name into user readable string.
*/
@Override
public String toString() {
return ("DNSName: " + name);
}
/**
* Get the raw DNSName value.
*/
public String getValue() {
return name;
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509/DeltaCRLIndicatorExtension.java 0000664 0000000 0000000 00000017710 14565430767 0033117 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.x509;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Array;
import java.math.BigInteger;
import java.security.cert.CertificateException;
import java.util.Enumeration;
import java.util.Vector;
import org.mozilla.jss.netscape.security.util.BigInt;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
/**
* Represent the Delta CRL Indicator Extension.
*
*
* The delta CRL indicator is a critical CRL extension that identifies a delta-CRL. The value of BaseCRLNumber
* identifies the CRL number of the base CRL that was used as the starting point in the generation of this delta- CRL.
* The delta-CRL contains the changes between the base CRL and the current CRL issued along with the delta-CRL.
*
* @see Extension
* @see CertAttrSet
*/
public class DeltaCRLIndicatorExtension extends Extension
implements CertAttrSet {
/**
*
*/
private static final long serialVersionUID = 7182919216525364676L;
/**
* Attribute name.
*/
public static final String NAME = "DeltaCRLIndicator";
public static final String NUMBER = "value";
/**
* The Object Identifier for this extension.
*/
public static final String OID = "2.5.29.27";
private BigInt baseCRLNumber = null;
static {
try {
OIDMap.addAttribute(DeltaCRLIndicatorExtension.class.getName(),
OID, NAME);
} catch (CertificateException e) {
}
}
// Encode this extension value
private void encodeThis() throws IOException {
if (baseCRLNumber == null)
throw new IOException("Unintialized delta CRL indicator extension");
try (DerOutputStream os = new DerOutputStream()) {
os.putInteger(this.baseCRLNumber);
this.extensionValue = os.toByteArray();
}
}
/**
* Create a DeltaCRLIndicatorExtension with the integer value.
* The criticality is set to true.
*
* @param baseCRLNum the value to be set for the extension.
*/
public DeltaCRLIndicatorExtension(int baseCRLNum) throws IOException {
this.baseCRLNumber = new BigInt(baseCRLNum);
this.extensionId = PKIXExtensions.DeltaCRLIndicator_Id;
this.critical = true;
encodeThis();
}
/**
* Create a DeltaCRLIndicatorExtension with the BigInteger value.
* The criticality is set to true.
*
* @param baseCRLNum the value to be set for the extension.
*/
public DeltaCRLIndicatorExtension(BigInteger baseCRLNum) throws IOException {
this.baseCRLNumber = new BigInt(baseCRLNum);
this.extensionId = PKIXExtensions.DeltaCRLIndicator_Id;
this.critical = true;
encodeThis();
}
/**
* Create a DeltaCRLIndicatorExtension with the BigInteger value.
*
* @param critical true if the extension is to be treated as critical.
* @param baseCRLNum the value to be set for the extension.
*/
public DeltaCRLIndicatorExtension(Boolean critical, BigInteger baseCRLNum)
throws IOException {
this.baseCRLNumber = new BigInt(baseCRLNum);
this.extensionId = PKIXExtensions.DeltaCRLIndicator_Id;
this.critical = critical.booleanValue();
encodeThis();
}
/**
* Create the extension from the passed DER encoded value of the same.
*
* @param critical true if the extension is to be treated as critical.
* @param value Array of DER encoded bytes of the actual value.
* @exception IOException on error.
*/
public DeltaCRLIndicatorExtension(Boolean critical, Object value)
throws IOException {
this.extensionId = PKIXExtensions.DeltaCRLIndicator_Id;
this.critical = critical.booleanValue();
int len = Array.getLength(value);
byte[] extValue = new byte[len];
for (int i = 0; i < len; i++) {
extValue[i] = Array.getByte(value, i);
}
this.extensionValue = extValue;
DerValue val = new DerValue(extValue);
this.baseCRLNumber = val.getInteger();
}
/**
* Set the attribute value.
*/
@Override
public void set(String name, Object obj) throws IOException {
if (name.equalsIgnoreCase(NUMBER)) {
if (!(obj instanceof BigInteger)) {
throw new IOException("Attribute must be of type BigInteger.");
}
baseCRLNumber = new BigInt((BigInteger) obj);
} else {
throw new IOException("Attribute name not recognized by" +
" CertAttrSet:DeltaCRLIndicator.");
}
}
/**
* Get the attribute value.
*/
@Override
public Object get(String name) throws IOException {
if (name.equalsIgnoreCase(NUMBER)) {
if (baseCRLNumber == null)
return null;
else
return baseCRLNumber.toBigInteger();
} else {
throw new IOException("Attribute name not recognized by" +
" CertAttrSet:DeltaCRLIndicator.");
}
}
/**
* Delete the attribute value.
*/
@Override
public void delete(String name) throws IOException {
if (name.equalsIgnoreCase(NUMBER)) {
baseCRLNumber = null;
} else {
throw new IOException("Attribute name not recognized by" +
" CertAttrSet:DeltaCRLIndicator.");
}
}
/**
* Returns a printable representation of the DeltaCRLIndicatorExtension.
*/
@Override
public String toString() {
String s = super.toString() + "Delta CRL Indicator: " +
((baseCRLNumber == null) ? "" : baseCRLNumber.toString())
+ "\n";
return (s);
}
/**
* Decode the extension from the InputStream.
*
* @param in the InputStream to unmarshal the contents from.
* @exception IOException on decoding or validity errors.
*/
@Override
public void decode(InputStream in) throws IOException {
throw new IOException("Method not to be called directly.");
}
/**
* Write the extension to the DerOutputStream.
*
* @param out the DerOutputStream to write the extension to.
* @exception IOException on encoding errors.
*/
@Override
public void encode(OutputStream out) throws IOException {
DerOutputStream tmp = new DerOutputStream();
if (this.extensionValue == null) {
this.extensionId = PKIXExtensions.DeltaCRLIndicator_Id;
this.critical = true;
encodeThis();
}
super.encode(tmp);
out.write(tmp.toByteArray());
}
/**
* Return an enumeration of names of attributes existing within this
* attribute.
*/
@Override
public Enumeration getAttributeNames() {
Vector elements = new Vector<>();
elements.addElement(NUMBER);
return (elements.elements());
}
/**
* Return the name of this attribute.
*/
@Override
public String getName() {
return (NAME);
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509/DirStrConverter.java 0000664 0000000 0000000 00000014362 14565430767 0031072 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.x509;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.CharsetEncoder;
import org.mozilla.jss.netscape.security.util.ASN1CharStrConvMap;
import org.mozilla.jss.netscape.security.util.DerValue;
/**
* A DirStrConverter converts a string to a DerValue of ASN.1 Directory String,
* which is a CHOICE of Printable (subset of ASCII), T.61 (Teletex) or
* Universal String (UCS-4), and vice versa.
*
*
* The string to DerValue conversion is done as follows. If the string has only PrintableString characters it is
* converted to a ASN.1 Printable String using the PrintableString encoder from the global default ASN1CharStrConvMap.
* If it has only characters covered in the PrintableString or T.61 character set it is converted to a ASN.1 T.61 string
* using the T.61 encoder from the ASN1CharStrCovnMap. Otherwise it is converted to a ASN.1 UniversalString (UCS-4
* character set) which covers all characters.
*
* @see AVAValueConverter
* @see ASN1CharStrConvMap
*
* @author Lily Hsiao, Slava Galperin at Netscape Communications, Inc.
*/
public class DirStrConverter implements AVAValueConverter {
// public constructors
/**
* Constructs a DirStrConverter.
*/
public DirStrConverter() {
}
// public functions
/**
* Converts a string to a DER encoded ASN1 Directory String, which is a
* CHOICE of PrintableString, T.61String or UniversalString.
* The string is taken as is i.e. should not be in Ldap DN string syntax.
*
* @param ds a string representing a directory string value.
*
* @return a DerValue
*
* @exception IOException if the string cannot be converted, such as
* when a UniversalString encoder
* isn't available and the string contains
* characters covered only in the universal
* string (or UCS-4) character set.
*/
private static byte[] DefEncodingOrder =
new byte[] {
DerValue.tag_UTF8String,
DerValue.tag_PrintableString,
DerValue.tag_T61String,
DerValue.tag_UniversalString
};
public static synchronized void
setDefEncodingOrder(byte[] defEncodingOrder) {
DefEncodingOrder = defEncodingOrder;
}
@Override
public DerValue getValue(String ds)
throws IOException {
return getValue(ds, DefEncodingOrder);
}
/**
* Like getValue(String) with specified DER tags as encoding order.
*/
@Override
public DerValue getValue(String valueString, byte[] tags) throws IOException {
// try to convert to printable, then t61 the universal -
// i.e. from minimal to the most liberal.
if (tags == null || tags.length == 0)
tags = DefEncodingOrder;
for (int i = 0; i < tags.length; i++) {
try {
CharsetEncoder encoder = ASN1CharStrConvMap.getDefault().getEncoder(tags[i]);
if (encoder == null)
continue;
CharBuffer charBuffer = CharBuffer.wrap(valueString.toCharArray());
ByteBuffer byteBuffer = encoder.encode(charBuffer);
return new DerValue(tags[i], byteBuffer.array(), byteBuffer.arrayOffset(), byteBuffer.limit());
} catch (CharacterCodingException e) {
continue;
}
}
throw new IOException(
"Cannot convert the directory string value to a ASN.1 type");
}
/**
* Creates a DerValue from a BER encoded value, obtained from for example
* a attribute value in octothorpe form of a Ldap DN string.
* Checks if the BER encoded value is legal for a DirectoryString.
*
* NOTE: currently only supports DER encoding for the BER encoded value.
*
* @param berByteStream Byte array of a BER encoded value.
*
* @return DerValue object.
*
* @exception IOException If the BER value cannot be converted to a
* valid Directory String DER value.
*/
@Override
public DerValue getValue(byte[] berByteStream)
throws IOException {
DerValue value = new DerValue(berByteStream);
/*
if (value.tag != DerValue.tag_PrintableString &&
value.tag != DerValue.tag_T61String &&
value.tag != DerValue.tag_UniversalString)
throw new IOException("Invalid Directory String AVA Value");
*/
return value;
}
/**
* Converts a DerValue to a string.
* The string is not in any syntax, such as RFC1779 string syntax.
*
* @param avaValue a DerValue
* @return a string if the value can be converted.
* @exception IOException if a decoder needed for the
* conversion is not available.
*/
@Override
public String getAsString(DerValue avaValue)
throws IOException {
/*
if (avaValue.tag != DerValue.tag_PrintableString &&
avaValue.tag != DerValue.tag_BMPString &&
avaValue.tag != DerValue.tag_UniversalString &&
avaValue.tag != DerValue.tag_T61String)
throw new IllegalArgumentException(
"Invalid Directory String value");
// NOTE will return null if a decoder is not available.
*/
return avaValue.getASN1CharString();
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509/DisplayText.java 0000664 0000000 0000000 00000005066 14565430767 0030246 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.x509;
import java.io.IOException;
import java.io.Serializable;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
/**
* Represent the DisplayText.
*
* DisplayText ::= CHOICE {
* visibleString VisibleString (SIZE (1..200)),
* bmpString BMPString (SIZE (1..200)),
* utf8String UTF8String (SIZE (1..200)),
* }
*
* @author Thomas Kwan
*/
public class DisplayText implements Serializable {
private static final long serialVersionUID = -6521458152495173328L;
/** Tag value indicating an ASN.1 "BMPString" value. */
public final static byte tag_IA5String = 0x16;
public final static byte tag_BMPString = 0x1E;
public final static byte tag_VisibleString = 0x1A;
public final static byte tag_UTF8String = 0x0C;
private byte mTag;
private String mS = null;
public DisplayText(byte tag, String s) {
mTag = tag;
mS = s;
}
public DisplayText(DerValue val) throws IOException {
mTag = val.tag;
mS = val.getAsString();
}
/**
* Write the DisplayText to the DerOutputStream.
*
* @param out the DerOutputStream to write the object to.
* @exception IOException on errors.
*/
public void encode(DerOutputStream out) throws IOException {
out.putStringType(mTag, mS);
}
public String getText() {
return mS;
}
@Override
public String toString() {
if (mTag == tag_IA5String) {
return "IA5String: " + mS;
} else if (mTag == tag_BMPString) {
return "BMPString: " + mS;
} else if (mTag == tag_VisibleString) {
return "VisibleString: " + mS;
} else {
return "UTF8String: " + mS;
}
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509/EDIPartyName.java 0000664 0000000 0000000 00000012253 14565430767 0030212 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.x509;
import java.io.IOException;
import org.mozilla.jss.netscape.security.util.DerInputStream;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
/**
* This class defines the EDIPartyName of the GeneralName choice.
* The ASN.1 syntax for this is:
*
*
* EDIPartyName ::= SEQUENCE {
* nameAssigner [0] DirectoryString OPTIONAL,
* partyName [1] DirectoryString }
*
*
* @author Hemma Prafullchandra
* @version 1.2
* @see GeneralName
* @see GeneralNames
* @see GeneralNameInterface
*/
public class EDIPartyName implements GeneralNameInterface {
/**
*
*/
private static final long serialVersionUID = -8669257424766789063L;
// Private data members
private static final byte TAG_ASSIGNER = 0;
private static final byte TAG_PARTYNAME = 1;
private String assigner = null;
private String party = null;
/**
* Create the EDIPartyName object from the specified names.
*
* @param assignerName the name of the assigner
* @param partyName the name of the EDI party.
*/
public EDIPartyName(String assignerName, String partyName) {
this.assigner = assignerName;
this.party = partyName;
}
/**
* Create the EDIPartyName object from the specified name.
*
* @param partyName the name of the EDI party.
*/
public EDIPartyName(String partyName) {
this.party = partyName;
}
/**
* Create the EDIPartyName object from the passed encoded Der value.
*
* @param derValue the encoded DER EDIPartyName.
* @exception IOException on error.
*/
public EDIPartyName(DerValue derValue) throws IOException {
DerInputStream in = new DerInputStream(derValue.toByteArray());
DerValue[] seq = in.getSequence(2);
int len = seq.length;
if (len < 1 || len > 2)
throw new IOException("Invalid encoding of EDIPartyName");
for (int i = 0; i < len; i++) {
DerValue opt = seq[i];
if (opt.isContextSpecific(TAG_ASSIGNER) &&
!opt.isConstructed()) {
if (assigner != null)
throw new IOException("Duplicate nameAssigner found in"
+ " EDIPartyName");
opt = opt.data.getDerValue();
assigner = opt.getAsString();
}
if (opt.isContextSpecific(TAG_PARTYNAME) &&
!opt.isConstructed()) {
if (party != null)
throw new IOException("Duplicate partyName found in"
+ " EDIPartyName");
opt = opt.data.getDerValue();
party = opt.getAsString();
}
}
}
/**
* Return the type of the GeneralName.
*/
@Override
public int getType() {
return (GeneralNameInterface.NAME_EDI);
}
/**
* Encode the EDI party name into the DerOutputStream.
*
* @param out the DER stream to encode the EDIPartyName to.
* @exception IOException on encoding errors.
*/
@Override
public void encode(DerOutputStream out) throws IOException {
DerOutputStream tagged = new DerOutputStream();
DerOutputStream tmp = new DerOutputStream();
if (assigner != null) {
DerOutputStream tmp2 = new DerOutputStream();
// XXX - shd check is chars fit into PrintableString
tmp2.putPrintableString(assigner);
tagged.write(DerValue.createTag(DerValue.TAG_CONTEXT,
false, TAG_ASSIGNER), tmp2);
}
if (party == null) {
tagged.close();
tmp.close();
throw new IOException("Cannot have null partyName");
}
// XXX - shd check is chars fit into PrintableString
tmp.putPrintableString(party);
tagged.write(DerValue.createTag(DerValue.TAG_CONTEXT,
false, TAG_PARTYNAME), tmp);
out.write(DerValue.tag_Sequence, tagged);
}
/**
* Return the printable string.
*/
@Override
public String toString() {
return ("EDIPartyName: " +
((assigner == null) ? "" :
(" nameAssigner = " + assigner + ","))
+ " partyName = " + party);
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509/Extension.java 0000664 0000000 0000000 00000014061 14565430767 0027743 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.x509;
import java.io.IOException;
import java.io.Serializable;
import org.mozilla.jss.netscape.security.util.DerInputStream;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
import org.mozilla.jss.netscape.security.util.ObjectIdentifier;
/**
* Represent a X509 Extension Attribute.
*
*
* Extensions are addiitonal attributes which can be inserted in a X509 v3 certificate. For example a
* "Driving License Certificate" could have the driving license number as a extension.
*
*
* Extensions are represented as a sequence of the extension identifier (Object Identifier), a boolean flag stating
* whether the extension is to be treated as being critical and the extension value itself (this is again a DER encoding
* of the extension value).
*
*
* ASN.1 definition of Extension:
* Extension ::= SEQUENCE {
* ExtensionId OBJECT IDENTIFIER,
* critical BOOLEAN DEFAULT FALSE,
* extensionValue OCTET STRING
* }
*
*
* @author Amit Kapoor
* @author Hemma Prafullchandra
* @version 1.9
*/
public class Extension implements Serializable {
private static final long serialVersionUID = -643549610716024753L;
protected ObjectIdentifier extensionId = null;
protected boolean critical = false;
protected byte[] extensionValue = null;
/**
* Default constructor. Used only by sub-classes.
*/
public Extension() {
}
/**
* Constructs an extension from a DER encoded array of bytes.
*/
public Extension(DerValue derVal) throws IOException {
DerInputStream in = derVal.toDerInputStream();
// Object identifier
extensionId = in.getOID();
// If the criticality flag was false, it will not have been encoded.
DerValue val = in.getDerValue();
if (val.tag == DerValue.tag_Boolean) {
critical = val.getBoolean();
// Extension value (DER encoded)
val = in.getDerValue();
extensionValue = val.getOctetString();
} else {
critical = false;
extensionValue = val.getOctetString();
}
}
/**
* Constructs an Extension from individual components of ObjectIdentifier,
* criticality and the DER encoded OctetString.
*
* @param extensionId the ObjectIdentifier of the extension
* @param critical the boolean indicating if the extension is critical
* @param extensionValue the DER encoded octet string of the value.
*/
public Extension(ObjectIdentifier extensionId, boolean critical,
byte[] extensionValue) throws IOException {
this.extensionId = extensionId;
this.critical = critical;
// passed in a DER encoded octet string, strip off the tag
// and length
DerValue inDerVal = new DerValue(extensionValue);
this.extensionValue = inDerVal.getOctetString();
}
/**
* Constructs an Extension from another extension. To be used for
* creating decoded subclasses.
*
* @param ext the extension to create from.
*/
public Extension(Extension ext) {
this.extensionId = ext.extensionId;
this.critical = ext.critical;
this.extensionValue = ext.extensionValue;
}
/**
* Write the extension to the DerOutputStream.
*
* @param out the DerOutputStream to write the extension to.
* @exception IOException on encoding errors
*/
public void encode(DerOutputStream out) throws IOException {
if (extensionId == null)
throw new IOException("Null OID to encode for the extension!");
DerOutputStream bytes = new DerOutputStream();
bytes.putOID(extensionId);
if (critical)
bytes.putBoolean(critical);
if (extensionValue != null)
bytes.putOctetString(extensionValue);
out.write(DerValue.tag_Sequence, bytes);
}
/**
* Returns true if extension is critical.
*/
public boolean isCritical() {
return (critical);
}
public void setCritical(boolean c) {
critical = c;
}
public void clearValue() {
extensionValue = null;
}
/**
* Returns the ObjectIdentifier of the extension.
*/
public ObjectIdentifier getExtensionId() {
return (extensionId);
}
public void setExtensionId(ObjectIdentifier oid) {
extensionId = oid;
}
/**
* Returns the extension value as an byte array for further processing.
* Note, this is the raw DER value of the extension, not the DER
* encoded octet string which is in the certificate.
*/
public byte[] getExtensionValue() {
if (extensionValue == null)
return null;
byte[] dup = new byte[extensionValue.length];
System.arraycopy(extensionValue, 0, dup, 0, dup.length);
return dup;
}
public void setExtensionValue(byte value[]) {
extensionValue = value;
}
/**
* Returns the Extension in user readable form.
*/
@Override
public String toString() {
String s = "ObjectId: " + extensionId.toString();
if (critical) {
s += " Criticality=true\n";
} else {
s += " Criticality=false\n";
}
return (s);
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509/Extensions.java 0000664 0000000 0000000 00000020201 14565430767 0030117 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.x509;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Array;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.security.cert.CertificateException;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import org.mozilla.jss.netscape.security.util.DerInputStream;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
/**
* This class defines the Extensions attribute for the Certificate.
*
* @author Amit Kapoor
* @author Hemma Prafullchandra
* @version 1.11
* @see CertAttrSet
*/
public class Extensions extends Vector
implements CertAttrSet {
/**
*
*/
private static final long serialVersionUID = 4597917347772057433L;
/**
* Identifier for this attribute, to be used with the
* get, set, delete methods of Certificate, x509 type.
*/
public static final String IDENT = "x509.info.extensions";
/**
* name
*/
public static final String NAME = "extensions";
private Hashtable map;
// Parse the encoded extension
public void parseExtension(Extension ext) throws IOException {
try {
@SuppressWarnings("unchecked")
Class extClass = (Class) OIDMap.getClass(ext.getExtensionId());
if (extClass == null) { // Unsupported extension
if (ext.isCritical()) {
throw new IOException("Unsupported CRITICAL extension: "
+ ext.getExtensionId());
} else {
map.put(ext.getExtensionId().toString(), ext);
addElement(ext);
return;
}
}
Class>[] params = { Boolean.class, Object.class };
Constructor cons = extClass.getConstructor(params);
byte[] extData = ext.getExtensionValue();
int extLen = extData.length;
Object value = Array.newInstance(byte.class, extLen);
for (int i = 0; i < extLen; i++) {
Array.setByte(value, i, extData[i]);
}
Object[] passed = new Object[] { Boolean.valueOf(ext.isCritical()),
value };
CertAttrSet certExt = cons.newInstance(passed);
map.put(certExt.getName(), (Extension) certExt);
addElement((Extension) certExt);
} catch (NoSuchMethodException nosuch) {
throw new IOException(nosuch.toString());
} catch (InvocationTargetException invk) {
throw new IOException(invk.getTargetException().toString());
} catch (Exception e) {
throw new IOException(e.toString());
}
}
/**
* Default constructor for the certificate attribute.
*/
public Extensions() {
map = new Hashtable<>();
}
/**
* Create the object, decoding the values from the passed DER stream.
*
* @param in the DerInputStream to read the Extension from.
* @exception IOException on decoding errors.
*/
public Extensions(DerInputStream in)
throws IOException {
map = new Hashtable<>();
DerValue[] exts = in.getSequence(5);
for (int i = 0; i < exts.length; i++) {
Extension ext = new Extension(exts[i]);
parseExtension(ext);
}
}
/**
* Decode the extensions from the InputStream.
*
* @param in the InputStream to unmarshal the contents from.
* @exception IOException on decoding or validity errors.
*/
@Override
public void decode(InputStream in) throws IOException {
DerValue val = new DerValue(in);
DerInputStream str = val.toDerInputStream();
map = new Hashtable<>();
DerValue[] exts = str.getSequence(5);
for (int i = 0; i < exts.length; i++) {
Extension ext = new Extension(exts[i]);
parseExtension(ext);
}
}
/**
* Encode the extensions in DER form to the stream.
*
* @param out the DerOutputStream to marshal the contents to.
* @exception CertificateException on encoding errors.
* @exception IOException on errors.
*/
@Override
public void encode(OutputStream out)
throws CertificateException, IOException {
DerOutputStream extOut = new DerOutputStream();
for (int i = 0; i < size(); i++) {
Object thisOne = elementAt(i);
if (thisOne instanceof CertAttrSet)
((CertAttrSet) thisOne).encode(extOut);
else if (thisOne instanceof Extension)
((Extension) thisOne).encode(extOut);
else
throw new CertificateException("Invalid extension object");
}
try (DerOutputStream seq = new DerOutputStream()) {
seq.write(DerValue.tag_Sequence, extOut);
out.write(seq.toByteArray());
}
}
/**
* Set the attribute value.
*
* @param name the extension name used in the cache.
* @param obj the object to set.
* @exception IOException if the object could not be cached.
*/
@Override
public void set(String name, Object obj) throws IOException {
map.put(name, (Extension) obj);
addElement((Extension) obj);
}
/**
* Get the attribute value.
*
* @param name the extension name used in the lookup.
* @exception IOException if named extension is not found.
*/
@Override
public Object get(String name) throws IOException {
Object obj = map.get(name);
if (obj == null) {
throw new IOException("No extension found with name " + name);
}
return (obj);
}
/**
* Delete the attribute value.
*
* @param name the extension name used in the lookup.
* @exception IOException if named extension is not found.
*/
@Override
public void delete(String name) throws IOException {
Object obj = map.get(name);
if (obj == null) {
throw new IOException("No extension found with name " + name);
}
map.remove(name);
removeElement(obj);
}
/**
* Return an enumeration of names of attributes existing within this
* attribute.
*/
@Override
public Enumeration getAttributeNames() {
return map.keys();
}
/**
* Return the name of this attribute.
*/
@Override
public String getName() {
return (NAME);
}
@Override
public synchronized int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + ((map == null) ? 0 : map.hashCode());
return result;
}
@Override
public synchronized boolean equals(Object obj) {
if (this == obj)
return true;
if (!super.equals(obj))
return false;
if (getClass() != obj.getClass())
return false;
Extensions other = (Extensions) obj;
if (map == null) {
if (other.map != null)
return false;
} else if (!map.equals(other.map))
return false;
return true;
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509/ExtensionsRequested.java 0000664 0000000 0000000 00000012615 14565430767 0032013 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.x509;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.cert.CertificateException;
import java.util.Enumeration;
import java.util.Vector;
import org.mozilla.jss.netscape.security.util.DerInputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
public class ExtensionsRequested implements CertAttrSet {
public static final String NAME = "EXTENSIONS_REQUESTED";
public static final String KUE_DIGITAL_SIGNATURE = "kue_digital_signature";
public static final String KUE_KEY_ENCIPHERMENT = "kue_key_encipherment";
private String kueDigitalSignature = "false";
private String kueKeyEncipherment = "false";
private Vector exts = new Vector<>();
public ExtensionsRequested(Object stuff) throws IOException {
ByteArrayInputStream is = new ByteArrayInputStream((byte[]) stuff);
try {
decode(is);
} catch (CertificateException | IOException e) {
throw new IOException("Error decoding extensions: " + e.getMessage());
}
}
@Override
public void encode(OutputStream out)
throws CertificateException, IOException {
}
@Override
public void decode(InputStream in)
throws CertificateException, IOException {
DerValue derVal = new DerValue(in);
construct(derVal);
}
@Override
public void set(String name, Object obj)
throws CertificateException, IOException {
}
@Override
public Object get(String name)
throws CertificateException, IOException {
if (name.equalsIgnoreCase(KUE_DIGITAL_SIGNATURE)) {
return kueDigitalSignature;
}
if (name.equalsIgnoreCase(KUE_KEY_ENCIPHERMENT)) {
return kueKeyEncipherment;
}
throw new IOException("Unsupported attribute queried");
}
@Override
public void delete(String name)
throws CertificateException, IOException {
}
@Override
public Enumeration getAttributeNames() {
return (new Vector()).elements();
}
@Override
public String getName() {
return NAME;
}
/**
* construct - expects this in the inputstream (from the router):
*
* 211 30 31: SEQUENCE {
* 213 06 10: OBJECT IDENTIFIER '2 16 840 1 113733 1 9 8'
* 225 31 17: SET {
* 227 04 15: OCTET STRING, encapsulates {
* 229 30 13: SEQUENCE {
* 231 30 11: SEQUENCE {
* 233 06 3: OBJECT IDENTIFIER keyUsage (2 5 29 15)
* 238 04 4: OCTET STRING
* : 03 02 05 A0
* : }
* : }
* : }
*
* or this (from IRE client):
*
* 262 30 51: SEQUENCE {
* 264 06 9: OBJECT IDENTIFIER extensionReq (1 2 840 113549 1 9 14)
* 275 31 38: SET {
* 277 30 36: SEQUENCE {
* 279 30 34: SEQUENCE {
* 281 06 3: OBJECT IDENTIFIER subjectAltName (2 5 29 17)
* 286 04 27: OCTET STRING
* : 30 19 87 04 D0 0C 3E 6F 81 03 61 61 61 82 0C 61
* : 61 61 2E 6D 63 6F 6D 2E 63 6F 6D
* : }
* : }
* : }
* : }
*/
private void construct(DerValue dv) throws IOException {
DerInputStream stream = null;
try { // try decoding as sequence first
stream = dv.toDerInputStream();
stream.getDerValue(); // consume stream
stream.reset();
stream.getSequence(2); // consume stream
} catch (IOException ioe) {
// if it failed, the outer sequence may be
// encapsulated in an octet string, as in the first
// example above
byte[] octetString = dv.getOctetString();
// Make a new input stream from the byte array,
// and re-parse it as a sequence.
dv = new DerValue(octetString);
stream = dv.toDerInputStream();
stream.getSequence(2); // consume stream
}
// now, the stream will be in the correct format
stream.reset();
DerValue extDv = null;
// stream.available() will return the remaining bytes in the stream precisely
// (since it's a ByteArrayInputStream). DER values are at least 2 bytes long:
// (see https://letsencrypt.org/docs/a-warm-welcome-to-asn1-and-der/)
// IOException will raise only for malformed DER values
while (stream.available() >= 2) {
extDv = stream.getDerValue();
Extension ext = new Extension(extDv);
exts.addElement(ext);
}
}
public Vector getExtensions() {
return exts;
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509/FreshestCRLExtension.java 0000664 0000000 0000000 00000032452 14565430767 0032014 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.x509;
import java.io.BufferedOutputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.security.cert.CertificateException;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Vector;
import org.mozilla.jss.asn1.ASN1Util;
import org.mozilla.jss.asn1.InvalidBERException;
import org.mozilla.jss.asn1.SEQUENCE;
import org.mozilla.jss.netscape.security.util.BitArray;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* An extension that tells applications where to find
* the latest (freshest) delta CRL for this certificate
* or full CRL.
*
*
* cRLDistributionPoints ::= SEQUENCE SIZE (1..MAX) OF DistributionPoint
*
* DistributionPoint ::= SEQUENCE {
* distributionPoint [0] DistributionPointName OPTIONAL,
* reasons [1] ReasonFlags OPTIONAL,
* cRLIssuer [2] GeneralNames OPTIONAL }
*
* DistributionPointName ::= CHOICE {
* fullName [0] GeneralNames,
* nameRelativeToCRLIssuer [1] RelativeDistinguishedName }
*
* ReasonFlags ::= BIT STRING {
* unused (0),
* keyCompromise (1),
* cACompromise (2),
* affiliationChanged (3),
* superseded (4),
* cessationOfOperation (5),
* certificateHold (6) }
*
*/
public class FreshestCRLExtension extends Extension
implements CertAttrSet {
/**
*
*/
private static final long serialVersionUID = -8040203589629281781L;
private static final Logger logger = LoggerFactory.getLogger(FreshestCRLExtension.class);
// vector of CRLDistributionPoint
private SEQUENCE distributionPoints = new SEQUENCE();
public FreshestCRLExtension() {
this.extensionId = PKIXExtensions.FreshestCRL_Id;
this.critical = false;
}
// Cached DER-encoding to improve performance.
private byte[] cachedEncoding = null;
// Attribute name
public static final String NAME = "FreshestCRL";
// The Object Identifier for this extension.
public static final String OID = "2.5.29.46";
static {
try {
OIDMap.addAttribute(FreshestCRLExtension.class.getName(),
OID, NAME);
} catch (CertificateException e) {
}
}
/**
* This constructor is called by the CertificateExtensions class to decode
* an extension whose OID indicates it is a CRLDistributionsPoints
* extension.
*/
public FreshestCRLExtension(Boolean critical, Object value)
//throws IOException
{
try {
this.extensionId = PKIXExtensions.FreshestCRL_Id;
this.critical = critical.booleanValue();
this.extensionValue = ((byte[]) value).clone();
// decode the value
try {
SEQUENCE.OF_Template seqOfCRLDP =
new SEQUENCE.OF_Template(CRLDistributionPoint.getTemplate());
distributionPoints =
(SEQUENCE) ASN1Util.decode(seqOfCRLDP, extensionValue);
} catch (InvalidBERException e) {
throw new IOException("Invalid BER-encoding: " + e, e);
}
} catch (IOException e) {
logger.error("Error decoding freshest CRL", e);
}
}
/**
* Creates a new FreshestCRL extension, with the given
* distribution point as the first element.
*/
public FreshestCRLExtension(CRLDistributionPoint dp) {
this.extensionId = PKIXExtensions.FreshestCRL_Id;
this.critical = false;
distributionPoints.addElement(dp);
}
/**
* Adds an additional distribution point to the end of the sequence.
*/
public void addPoint(CRLDistributionPoint dp) {
distributionPoints.addElement(dp);
cachedEncoding = null;
}
/**
* Returns the number of distribution points in the sequence.
*/
public int getNumPoints() {
return distributionPoints.size();
}
/**
* Returns the DistributionPoint at the given index in the sequence.
*/
public CRLDistributionPoint getPointAt(int index) {
return (CRLDistributionPoint) distributionPoints.elementAt(index);
}
/**
* Sets the criticality of this extension. PKIX dictates that this
* extension SHOULD NOT be critical, so applications can make it critical
* if they have a very good reason. By default, the extension is not
* critical.
*/
@Override
public void setCritical(boolean critical) {
this.critical = critical;
}
/**
* Encodes this extension to the given DerOutputStream.
* This method re-encodes each time it is called, so it is not very
* efficient.
*/
@Override
public void encode(DerOutputStream out) throws IOException {
extensionValue = ASN1Util.encode(distributionPoints);
super.encode(out);
}
/**
* Should be called if any change is made to this data structure
* so that the cached DER encoding can be discarded.
*/
public void flushCachedEncoding() {
cachedEncoding = null;
}
/////////////////////////////////////////////////////////////
// CertAttrSet interface
// This interface is not really appropriate for this extension
// because it is so complicated. Therefore, we only provide a
// minimal implementation.
/////////////////////////////////////////////////////////////
@Override
public String toString() {
return NAME;
}
/**
* DER-encodes this extension to the given OutputStream.
*/
@Override
public void encode(OutputStream ostream)
throws CertificateException, IOException {
if (cachedEncoding == null) {
// only re-encode if necessary
DerOutputStream tmp = new DerOutputStream();
encode(tmp);
cachedEncoding = tmp.toByteArray();
}
ostream.write(cachedEncoding);
}
@Override
public void decode(InputStream in)
throws CertificateException, IOException {
throw new IOException("Not supported");
}
@Override
public void set(String name, Object obj)
throws CertificateException, IOException {
throw new IOException("Attribute name not recognized by " +
"CertAttrSet:FreshestCRLExtension");
}
@Override
public Object get(String name)
throws CertificateException, IOException {
throw new IOException("Attribute name not recognized by " +
"CertAttrSet:FreshestCRLExtension");
}
@Override
public void delete(String name)
throws CertificateException, IOException {
throw new IOException("Attribute name not recognized by " +
"CertAttrSet:FreshestCRLExtension");
}
/*
* TODO replacewith empty collection
*/
@Override
public Enumeration getAttributeNames() {
return (new Vector()).elements();
}
@Override
public String getName() {
return NAME;
}
/**
* Test driver.
*/
public static void main(String args[]) {
BufferedOutputStream bos = null;
try {
if (args.length != 1) {
System.out.println("Usage: FreshestCRLExtentions " +
"");
System.exit(-1);
}
bos = new BufferedOutputStream(
new FileOutputStream(args[0]));
// URI only
CRLDistributionPoint cdp = new CRLDistributionPoint();
URIName uri = new URIName("http://www.mycrl.com/go/here");
GeneralNames generalNames = new GeneralNames();
generalNames.addElement(uri);
cdp.setFullName(generalNames);
FreshestCRLExtension crldpExt =
new FreshestCRLExtension(cdp);
// DN only
cdp = new CRLDistributionPoint();
X500Name dn = new X500Name("CN=Otis Smith,E=otis@fedoraproject.org" +
",OU=Certificate Server,O=Fedora,C=US");
generalNames = new GeneralNames();
generalNames.addElement(dn);
cdp.setFullName(generalNames);
crldpExt.addPoint(cdp);
// DN + reason
BitArray ba = new BitArray(5, new byte[] { (byte) 0x28 });
cdp = new CRLDistributionPoint();
cdp.setFullName(generalNames);
cdp.setReasons(ba);
crldpExt.addPoint(cdp);
// relative DN + reason + crlIssuer
cdp = new CRLDistributionPoint();
RDN rdn = new RDN("OU=foobar dept");
cdp.setRelativeName(rdn);
cdp.setReasons(ba);
cdp.setCRLIssuer(generalNames);
crldpExt.addPoint(cdp);
crldpExt.setCritical(true);
crldpExt.encode(bos);
} catch (Exception e) {
e.printStackTrace();
} finally {
if (bos != null) {
try {
bos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
/**
* Represents a reason that a cert may be revoked. These reasons are
* expressed in a ReasonFlags bit string.
*/
public static class Reason {
private String name;
private byte bitMask;
private Reason() {
}
private Reason(String name, byte bitMask) {
this.name = name;
this.bitMask = bitMask;
map.put(name, this);
list.addElement(this);
}
private static Hashtable map = new Hashtable<>();
private static Vector list = new Vector<>();
public static Reason fromString(String name) {
return map.get(name);
}
public String getName() {
return name;
}
public byte getBitMask() {
return bitMask;
}
/**
* Given a bit array representing reason flags, extracts the reasons
* and returns them as an array.
*
* @param bitFlags A bit vector containing reason flags.
* @return An array of reasons contained in the bit vector.
* May be zero-length but will not be null.
*/
public static Reason[] bitArrayToReasonArray(byte bitFlags) {
return bitArrayToReasonArray(new byte[] { bitFlags });
}
/**
* Given a bit array representing reason flags, extracts the reasons
* and returns them as an array. Currently, only the first byte
* of the bitflags are examined.
*
* @param bitFlags A bit vector containing reason flags. The format
* is big-endian (MSB first). Only the first byte is examined.
* @return An array of reasons contained in the bit vector.
* May be zero-length but will not be null.
*/
public static Reason[] bitArrayToReasonArray(byte[] bitFlags) {
byte first = bitFlags[0];
int size = list.size();
Vector result = new Vector<>();
for (int i = 0; i < size; i++) {
Reason r = list.elementAt(i);
byte b = r.getBitMask();
if ((first & b) != 0) {
result.addElement(r);
}
}
size = result.size();
Reason[] retval = new Reason[size];
for (int i = 0; i < size; i++) {
retval[i] = result.elementAt(i);
}
return retval;
}
public static final Reason UNUSED =
new Reason("unused", (byte) 0x80);
public static final Reason KEY_COMPROMISE =
new Reason("keyCompromise", (byte) 0x40);
public static final Reason CA_COMPROMISE =
new Reason("cACompromise", (byte) 0x20);
public static final Reason AFFILIATION_CHANGED =
new Reason("affiliationChanged", (byte) 0x10);
public static final Reason SUPERSEDED =
new Reason("superseded", (byte) 0x08);
public static final Reason CESSATION_OF_OPERATION =
new Reason("cessationOfOperation", (byte) 0x04);
public static final Reason CERTIFICATE_HOLD =
new Reason("certificateHold", (byte) 0x02);
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509/GeneralName.java 0000664 0000000 0000000 00000017702 14565430767 0030152 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.x509;
import java.io.IOException;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
/**
* This class implements the ASN.1 GeneralName object class.
*
* The ASN.1 syntax for this is:
*
*
* GeneralName ::= CHOICE {
* otherName [0] OtherName,
* rfc822Name [1] IA5String,
* dNSName [2] IA5String,
* x400Address [3] ORAddress,
* directoryName [4] Name,
* ediPartyName [5] EDIPartyName,
* uniformResourceIdentifier [6] IA5String,
* iPAddress [7] OCTET STRING,
* registeredID [8] OBJECT IDENTIFIER
* }
*
*
* @author Amit Kapoor
* @author Hemma Prafullchandra
* @version 1.7
*/
public class GeneralName implements GeneralNameInterface {
/**
*
*/
private static final long serialVersionUID = 2244101501095555042L;
// Private data members
private GeneralNameInterface name = null;
/**
* Default constructor for the class.
*
* @param name the selected CHOICE from the list.
*/
public GeneralName(GeneralNameInterface name) {
this.name = name;
}
/**
* Create the object from its DER encoded value.
*
* @param encName the DER encoded GeneralName.
*/
public GeneralName(DerValue encName) throws IOException {
short tag = (byte) (encName.tag & 0x1f);
// NB. this is always encoded with the IMPLICIT tag
// The checks only make sense if we assume implicit tagging,
// with explicit tagging the form is always constructed.
switch (tag) {
case GeneralNameInterface.NAME_RFC822:
if (encName.isContextSpecific() && !encName.isConstructed()) {
encName.resetTag(DerValue.tag_IA5String);
name = new RFC822Name(encName);
} else
throw new IOException("Invalid encoding of RFC822 name");
break;
case GeneralNameInterface.NAME_DNS:
if (encName.isContextSpecific() && !encName.isConstructed()) {
encName.resetTag(DerValue.tag_IA5String);
name = new DNSName(encName);
} else
throw new IOException("Invalid encoding of DNS name");
break;
case GeneralNameInterface.NAME_URI:
if (encName.isContextSpecific() && !encName.isConstructed()) {
encName.resetTag(DerValue.tag_IA5String);
name = new URIName(encName);
} else
throw new IOException("Invalid encoding of URI");
break;
case GeneralNameInterface.NAME_IP:
if (encName.isContextSpecific() && !encName.isConstructed()) {
encName.resetTag(DerValue.tag_OctetString);
name = new IPAddressName(encName);
} else
throw new IOException("Invalid encoding of IP address");
break;
case GeneralNameInterface.NAME_ANY:
if (encName.isContextSpecific() && encName.isConstructed()) {
encName.resetTag(DerValue.tag_OctetString);
name = new OtherName(encName);
} else
throw new IOException("Invalid encoding of other name");
break;
case GeneralNameInterface.NAME_OID:
if (encName.isContextSpecific() && !encName.isConstructed()) {
encName.resetTag(DerValue.tag_ObjectId);
name = new OIDName(encName);
} else
throw new IOException("Invalid encoding of OID name");
break;
case GeneralNameInterface.NAME_DIRECTORY:
if (encName.isContextSpecific() && encName.isConstructed()) {
// Unlike the other cases, DirectoryName is EXPLICITly
// tagged, because the X.500 Name type is a CHOICE.
// Therefore, the sequence is actually nested in the
// content of this value. We'll pretend it's an octet
// string so we can get at the content bytes.
encName.resetTag(DerValue.tag_OctetString);
byte[] content = encName.getOctetString();
name = new X500Name(content);
} else
throw new IOException("Invalid encoding of Directory name");
break;
case GeneralNameInterface.NAME_EDI:
if (encName.isContextSpecific() && encName.isConstructed()) {
encName.resetTag(DerValue.tag_Sequence);
name = new EDIPartyName(encName);
} else
throw new IOException("Invalid encoding of EDI name");
break;
default:
throw new IOException("Unrecognized GeneralName tag, ("
+ tag + ")");
}
}
/**
* Return the type of the general name.
*/
@Override
public int getType() {
return (name.getType());
}
/**
* Return the name as user readable string
*/
@Override
public String toString() {
return (name.toString());
}
/**
* Encode the name to the specified DerOutputStream.
*
* @param out the DerOutputStream to encode the the GeneralName to.
* @exception IOException on encoding errors.
*/
@Override
public void encode(DerOutputStream out) throws IOException {
DerOutputStream tmp = new DerOutputStream();
name.encode(tmp);
int nameType = name.getType();
boolean constructedForm;
if (nameType == GeneralNameInterface.NAME_ANY ||
nameType == GeneralNameInterface.NAME_X400 ||
nameType == GeneralNameInterface.NAME_DIRECTORY ||
nameType == GeneralNameInterface.NAME_EDI) {
constructedForm = true;
} else {
constructedForm = false;
}
if (nameType == GeneralNameInterface.NAME_DIRECTORY) {
// EXPLICIT tag, because Name is a CHOICE type
out.write(DerValue.createTag(DerValue.TAG_CONTEXT,
constructedForm, (byte) nameType), tmp);
} else {
// IMPLICIT tag, the default
out.writeImplicit(DerValue.createTag(DerValue.TAG_CONTEXT,
constructedForm, (byte) nameType), tmp);
}
}
@Override
public boolean validSingle() {
if (this == name) return false; // can't happen, but just in case...
return name.validSingle();
}
@Override
public boolean validSubtree() {
if (this == name) return false; // can't happen, but just in case...
return name.validSubtree();
}
/**
* Unwrap this GeneralName until we reach something that is not
* a GeneralName.
*/
public GeneralNameInterface unwrap() {
if (this == name)
return null; // can't happen, but just in case...
if (name instanceof GeneralName)
return ((GeneralName) name).unwrap();
else
return name;
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509/GeneralNameInterface.java 0000664 0000000 0000000 00000004607 14565430767 0031773 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.x509;
import java.io.IOException;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
/**
* This interface specifies the abstract methods which have to be
* implemented by all the members of the GeneralNames ASN.1 object.
*
* @author Amit Kapoor
* @author Hemma Prafullchandra
* @version 1.6
*/
public interface GeneralNameInterface extends java.io.Serializable {
/**
* The list of names supported.
*/
public static final int NAME_ANY = 0;
public static final int NAME_RFC822 = 1;
public static final int NAME_DNS = 2;
public static final int NAME_X400 = 3;
public static final int NAME_DIRECTORY = 4;
public static final int NAME_EDI = 5;
public static final int NAME_URI = 6;
public static final int NAME_IP = 7;
public static final int NAME_OID = 8;
/**
* Return the type of the general name, as
* defined above.
*/
int getType();
/**
* Encode the name to the specified DerOutputStream.
*
* @param out the DerOutputStream to encode the GeneralName to.
* @exception IOException thrown if the GeneralName could not be
* encoded.
*/
void encode(DerOutputStream out) throws IOException;
/**
* Whether the name is valid as a single name (e.g. for use in
* Subject Alternative Name extension).
*/
default boolean validSingle() {
return true;
}
/**
* Whether the name is valid as a subtree name (e.g. for use in
* Name Constraints extension)
*/
default boolean validSubtree() {
return true;
}
}
jss-5.5.0/base/src/main/java/org/mozilla/jss/netscape/security/x509/GeneralNames.java 0000664 0000000 0000000 00000012231 14565430767 0030325 0 ustar 00root root 0000000 0000000 // --- BEGIN COPYRIGHT BLOCK ---
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; version 2 of the License.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License along
// with this program; if not, write to the Free Software Foundation, Inc.,
// 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
//
// (C) 2007 Red Hat, Inc.
// All rights reserved.
// --- END COPYRIGHT BLOCK ---
package org.mozilla.jss.netscape.security.x509;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Vector;
import org.mozilla.jss.netscape.security.util.DerOutputStream;
import org.mozilla.jss.netscape.security.util.DerValue;
/**
* This object class represents the GeneralNames type required in
* X509 certificates.
*
* The ASN.1 syntax for this is:
*
*
* GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName
*
*
* @author Amit Kapoor
* @author Hemma Prafullchandra
* @version 1.7
*/
public class GeneralNames extends Vector {
/**
*
*/
private static final long serialVersionUID = 3204492869396713312L;
/**
* Create the GeneralNames, decoding from the passed DerValue.
*
*