@Override protected void doGet(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException { response.setHeader("Access-Control-Allow-Origin", "*"); try { if (server == null) { LOG.error("server in servlet not configured"); response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); response.setContentLength(0); return; } ResponderAndRelativeUri r = server.getResponderAndRelativeUri(request); if (r == null) { response.sendError(HttpServletResponse.SC_NOT_FOUND); return; } if (StringUtil.isNotBlank(r.getRelativeUri())) { response.sendError(HttpServletResponse.SC_NOT_FOUND); return; } Responder responder = r.getResponder(); HealthCheckResult healthResult = server.healthCheck(responder); if (healthResult.isHealthy()) { response.setStatus(HttpServletResponse.SC_OK); } else { response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); } response.setContentType(HealthCheckServlet.CT_RESPONSE); byte[] respBytes = healthResult.toJsonMessage(true).getBytes(); response.setContentLength(respBytes.length); response.getOutputStream().write(respBytes); } catch (EOFException e) { final String message = "connection reset by peer"; if (LOG.isErrorEnabled()) { LOG.warn(LogUtil.buildExceptionLogFormat(message), e.getClass().getName(), e.getMessage()); } LOG.debug(message, e); response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); response.setContentLength(0); } catch (Throwable t) { final String message = "Throwable thrown, this should not happen"; if (LOG.isErrorEnabled()) { LOG.error(LogUtil.buildExceptionLogFormat(message), t.getClass().getName(), t.getMessage()); } LOG.debug(message, t); response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); response.setContentLength(0); } response.flushBuffer(); } // method doGet
public void setSignerTypeMap(String signerTypeMap) { if (signerTypeMap == null) { LOG.debug("signerTypeMap is null"); return; } signerTypeMap = signerTypeMap.trim(); if (StringUtil.isBlank(signerTypeMap)) { LOG.debug("signerTypeMap is empty"); return; } StringTokenizer st = new StringTokenizer(signerTypeMap, " \t"); while (st.hasMoreTokens()) { String token = st.nextToken(); StringTokenizer st2 = new StringTokenizer(token, "="); if (st2.countTokens() != 2) { LOG.warn("invalid signerTypeMap entry '" + token + "'"); continue; } String alias = st2.nextToken(); if (signerTypeMapping.containsKey(alias)) { LOG.warn("signerType alias '" + alias + "' already defined, ignore map '" + token + "'"); continue; } String signerType = st2.nextToken(); signerTypeMapping.put(alias, signerType); LOG.info("add alias '" + alias + "' for signerType '" + signerType + "'"); } }
private static Set<P11SlotIdentifier> getSlots(final SlotsType type) throws ConfigurationException { if (type == null || CollectionUtil.isEmpty(type.getSlot())) { return null; } Set<P11SlotIdentifier> slots = new HashSet<>(); for (SlotType slotType : type.getSlot()) { Long slotId = null; if (slotType.getId() != null) { String str = slotType.getId().trim(); try { if (StringUtil.startsWithIgnoreCase(str, "0X")) { slotId = Long.parseLong(str.substring(2), 16); } else { slotId = Long.parseLong(str); } } catch (NumberFormatException e) { String message = "invalid slotId '" + str + "'"; LOG.error(message); throw new ConfigurationException(message); } } slots.add(new P11SlotIdentifier(slotType.getIndex(), slotId)); } return slots; }
public void setPkcs11ConfFile(final String confFile) { if (StringUtil.isBlank(confFile)) { this.pkcs11ConfFile = null; } else { this.pkcs11ConfFile = confFile; } }
@Override protected void doPost(final HttpServletRequest request, final HttpServletResponse response) throws ServletException, IOException { ResponderAndRelativeUri r = server.getResponderAndRelativeUri(request); if (r == null) { response.sendError(HttpServletResponse.SC_NOT_FOUND); return; } if (StringUtil.isNotBlank(r.getRelativeUri())) { response.sendError(HttpServletResponse.SC_NOT_FOUND); return; } processRequest(request, response, r, false); }
@Override protected Object _doExecute() throws Exception { P10RequestGenerator p10Gen = new P10RequestGenerator(); hashAlgo = hashAlgo.trim().toUpperCase(); if (hashAlgo.indexOf('-') != -1) { hashAlgo = hashAlgo.replaceAll("-", ""); } if (needExtensionTypes == null) { needExtensionTypes = new LinkedList<>(); } // SubjectAltNames List<Extension> extensions = new LinkedList<>(); if (isNotEmpty(subjectAltNames)) { extensions.add(P10RequestGenerator.createExtensionSubjectAltName(subjectAltNames, false)); needExtensionTypes.add(Extension.subjectAlternativeName.getId()); } // SubjectInfoAccess if (isNotEmpty(subjectInfoAccesses)) { extensions.add( P10RequestGenerator.createExtensionSubjectInfoAccess(subjectInfoAccesses, false)); needExtensionTypes.add(Extension.subjectInfoAccess.getId()); } // Keyusage if (isNotEmpty(keyusages)) { Set<KeyUsage> usages = new HashSet<>(); for (String usage : keyusages) { usages.add(KeyUsage.getKeyUsage(usage)); } org.bouncycastle.asn1.x509.KeyUsage extValue = X509Util.createKeyUsage(usages); ASN1ObjectIdentifier extType = Extension.keyUsage; extensions.add(new Extension(extType, false, extValue.getEncoded())); needExtensionTypes.add(extType.getId()); } // ExtendedKeyusage if (isNotEmpty(extkeyusages)) { Set<ASN1ObjectIdentifier> oids = new HashSet<>(SecurityUtil.textToASN1ObjectIdentifers(extkeyusages)); ExtendedKeyUsage extValue = X509Util.createExtendedUsage(oids); ASN1ObjectIdentifier extType = Extension.extendedKeyUsage; extensions.add(new Extension(extType, false, extValue.getEncoded())); needExtensionTypes.add(extType.getId()); } // QcEuLimitValue if (isNotEmpty(qcEuLimits)) { ASN1EncodableVector v = new ASN1EncodableVector(); for (String m : qcEuLimits) { StringTokenizer st = new StringTokenizer(m, ":"); try { String currencyS = st.nextToken(); String amountS = st.nextToken(); String exponentS = st.nextToken(); Iso4217CurrencyCode currency; try { int intValue = Integer.parseInt(currencyS); currency = new Iso4217CurrencyCode(intValue); } catch (NumberFormatException e) { currency = new Iso4217CurrencyCode(currencyS); } int amount = Integer.parseInt(amountS); int exponent = Integer.parseInt(exponentS); MonetaryValue monterayValue = new MonetaryValue(currency, amount, exponent); QCStatement statment = new QCStatement(ObjectIdentifiers.id_etsi_qcs_QcLimitValue, monterayValue); v.add(statment); } catch (Exception e) { throw new Exception("invalid qc-eu-limit '" + m + "'"); } } ASN1ObjectIdentifier extType = Extension.qCStatements; ASN1Sequence extValue = new DERSequence(v); extensions.add(new Extension(extType, false, extValue.getEncoded())); needExtensionTypes.add(extType.getId()); } // biometricInfo if (biometricType != null && biometricHashAlgo != null && biometricFile != null) { TypeOfBiometricData _biometricType; if (StringUtil.isNumber(biometricType)) { _biometricType = new TypeOfBiometricData(Integer.parseInt(biometricType)); } else { _biometricType = new TypeOfBiometricData(new ASN1ObjectIdentifier(biometricType)); } ASN1ObjectIdentifier _biometricHashAlgo = AlgorithmUtil.getHashAlg(biometricHashAlgo); byte[] biometricBytes = IoUtil.read(biometricFile); MessageDigest md = MessageDigest.getInstance(_biometricHashAlgo.getId()); md.reset(); byte[] _biometricDataHash = md.digest(biometricBytes); DERIA5String _sourceDataUri = null; if (biometricUri != null) { _sourceDataUri = new DERIA5String(biometricUri); } BiometricData biometricData = new BiometricData( _biometricType, new AlgorithmIdentifier(_biometricHashAlgo), new DEROctetString(_biometricDataHash), _sourceDataUri); ASN1EncodableVector v = new ASN1EncodableVector(); v.add(biometricData); ASN1ObjectIdentifier extType = Extension.biometricInfo; ASN1Sequence extValue = new DERSequence(v); extensions.add(new Extension(extType, false, extValue.getEncoded())); needExtensionTypes.add(extType.getId()); } else if (biometricType == null && biometricHashAlgo == null && biometricFile == null) { // Do nothing } else { throw new Exception( "either all of biometric triples (type, hash algo, file)" + " must be set or none of them should be set"); } if (isNotEmpty(needExtensionTypes) || isNotEmpty(wantExtensionTypes)) { ExtensionExistence ee = new ExtensionExistence( SecurityUtil.textToASN1ObjectIdentifers(needExtensionTypes), SecurityUtil.textToASN1ObjectIdentifers(wantExtensionTypes)); extensions.add( new Extension( ObjectIdentifiers.id_xipki_ext_cmpRequestExtensions, false, ee.toASN1Primitive().getEncoded())); } ConcurrentContentSigner identifiedSigner = getSigner(hashAlgo, new SignatureAlgoControl(rsaMgf1, dsaPlain)); Certificate cert = Certificate.getInstance(identifiedSigner.getCertificate().getEncoded()); X500Name subjectDN; if (subject != null) { subjectDN = getSubject(subject); } else { subjectDN = cert.getSubject(); } SubjectPublicKeyInfo subjectPublicKeyInfo = cert.getSubjectPublicKeyInfo(); ContentSigner signer = identifiedSigner.borrowContentSigner(); PKCS10CertificationRequest p10Req; try { p10Req = p10Gen.generateRequest(signer, subjectPublicKeyInfo, subjectDN, extensions); } finally { identifiedSigner.returnContentSigner(signer); } File file = new File(outputFilename); saveVerbose("saved PKCS#10 request to file", file, p10Req.getEncoded()); return null; }
private void initPkcs11ModuleConf() { if (p11Control != null) { return; } if (StringUtil.isBlank(pkcs11ConfFile)) { throw new IllegalStateException("pkcs11ConfFile is not set"); } try { JAXBContext jaxbContext = JAXBContext.newInstance(ObjectFactory.class); Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); SchemaFactory schemaFact = SchemaFactory.newInstance(javax.xml.XMLConstants.W3C_XML_SCHEMA_NS_URI); Schema schema = schemaFact.newSchema(getClass().getResource("/xsd/pkcs11-conf.xsd")); unmarshaller.setSchema(schema); @SuppressWarnings("unchecked") JAXBElement<PKCS11ConfType> rootElement = (JAXBElement<PKCS11ConfType>) unmarshaller.unmarshal(new File(pkcs11ConfFile)); PKCS11ConfType pkcs11Conf = rootElement.getValue(); ModulesType modulesType = pkcs11Conf.getModules(); Map<String, P11ModuleConf> confs = new HashMap<>(); for (ModuleType moduleType : modulesType.getModule()) { String name = moduleType.getName(); if (DEFAULT_P11MODULE_NAME.equals(name)) { throw new ConfigurationException( "invald module name " + DEFAULT_P11MODULE_NAME + ", it is reserved"); } if (confs.containsKey(name)) { throw new ConfigurationException( "multiple modules with the same module name is not permitted"); } P11PasswordRetriever pwdRetriever; PasswordsType passwordsType = moduleType.getPasswords(); if (passwordsType == null || CollectionUtil.isEmpty(passwordsType.getPassword())) { pwdRetriever = P11NullPasswordRetriever.INSTANCE; } else { pwdRetriever = new P11PasswordRetrieverImpl(); ((P11PasswordRetrieverImpl) pwdRetriever).setPasswordResolver(passwordResolver); for (PasswordType passwordType : passwordsType.getPassword()) { Set<P11SlotIdentifier> slots = getSlots(passwordType.getSlots()); ((P11PasswordRetrieverImpl) pwdRetriever) .addPasswordEntry(slots, new ArrayList<>(passwordType.getSinglePassword())); } } Set<P11SlotIdentifier> includeSlots = getSlots(moduleType.getIncludeSlots()); Set<P11SlotIdentifier> excludeSlots = getSlots(moduleType.getExcludeSlots()); final String osName = System.getProperty("os.name").toLowerCase(); String nativeLibraryPath = null; for (NativeLibraryType library : moduleType.getNativeLibraries().getNativeLibrary()) { List<String> osNames = library.getOs(); if (CollectionUtil.isEmpty(osNames)) { nativeLibraryPath = library.getPath(); } else { for (String entry : osNames) { if (osName.contains(entry.toLowerCase())) { nativeLibraryPath = library.getPath(); break; } } } if (nativeLibraryPath != null) { break; } } if (nativeLibraryPath == null) { throw new ConfigurationException("could not find PKCS#11 library for OS " + osName); } P11ModuleConf conf = new P11ModuleConf(name, nativeLibraryPath, pwdRetriever, includeSlots, excludeSlots); confs.put(name, conf); } final String defaultModuleName = modulesType.getDefaultModule(); if (confs.containsKey(defaultModuleName) == false) { throw new ConfigurationException("default module " + defaultModuleName + " is not defined"); } this.p11Control = new P11Control(defaultModuleName, new HashSet<>(confs.values())); } catch (JAXBException | SAXException | ConfigurationException e) { final String message = "invalid configuration file " + pkcs11ConfFile; if (LOG.isErrorEnabled()) { final String exceptionMessage; if (e instanceof JAXBException) { exceptionMessage = XMLUtil.getMessage((JAXBException) e); } else { exceptionMessage = e.getMessage(); } LOG.error( LogUtil.buildExceptionLogFormat(message), e.getClass().getName(), exceptionMessage); } LOG.debug(message, e); throw new RuntimeException(message); } }
/* * sigAlgoControl will be considered only if hashAlgo is not set * */ private ConcurrentContentSigner doCreateSigner( String type, final String conf, final String hashAlgo, final SignatureAlgoControl sigAlgoControl, final X509Certificate[] certificateChain) throws SignerException { if (signerTypeMapping.containsKey(type)) { type = signerTypeMapping.get(type); } if ("PKCS11".equalsIgnoreCase(type) || "PKCS12".equalsIgnoreCase(type) || "JKS".equalsIgnoreCase(type)) { CmpUtf8Pairs keyValues = new CmpUtf8Pairs(conf); String s = keyValues.getValue("parallelism"); int parallelism = defaultParallelism; if (s != null) { try { parallelism = Integer.parseInt(s); } catch (NumberFormatException e) { throw new SignerException("invalid parallelism " + s); } if (parallelism < 1) { throw new SignerException("invalid parallelism " + s); } } if ("PKCS11".equalsIgnoreCase(type)) { String pkcs11Module = keyValues.getValue("module"); if (pkcs11Module == null) { pkcs11Module = DEFAULT_P11MODULE_NAME; } s = keyValues.getValue("slot"); Integer slotIndex = (s == null) ? null : Integer.parseInt(s); s = keyValues.getValue("slot-id"); Long slotId = (s == null) ? null : Long.parseLong(s); if ((slotIndex == null && slotId == null) || (slotIndex != null && slotId != null)) { throw new SignerException("exactly one of slot (index) and slot-id must be specified"); } P11SlotIdentifier slot = new P11SlotIdentifier(slotIndex, slotId); String keyLabel = keyValues.getValue("key-label"); s = keyValues.getValue("key-id"); byte[] keyId = null; if (s != null) { keyId = Hex.decode(s); } if ((keyId == null && keyLabel == null) || (keyId != null && keyLabel != null)) { throw new SignerException("exactly one of key-id and key-label must be specified"); } P11KeyIdentifier keyIdentifier; if (keyId != null) { keyIdentifier = new P11KeyIdentifier(keyId); } else { keyIdentifier = new P11KeyIdentifier(keyLabel); } P11CryptService p11CryptService = getP11CryptService(pkcs11Module); P11ContentSignerBuilder signerBuilder = new P11ContentSignerBuilder(p11CryptService, slot, keyIdentifier, certificateChain); try { AlgorithmIdentifier signatureAlgId; if (hashAlgo == null) { signatureAlgId = getSignatureAlgoId(conf); } else { PublicKey pubKey; try { pubKey = getPkcs11PublicKey(pkcs11Module, slot, keyIdentifier); } catch (InvalidKeyException e) { throw new SignerException("invalid key: " + e.getMessage(), e); } signatureAlgId = AlgorithmUtil.getSignatureAlgoId(pubKey, hashAlgo, sigAlgoControl); } return signerBuilder.createSigner(signatureAlgId, parallelism); } catch (OperatorCreationException | NoSuchPaddingException | NoSuchAlgorithmException e) { throw new SignerException(e.getMessage(), e); } } else { String passwordHint = keyValues.getValue("password"); char[] password; if (passwordHint == null) { password = null; } else { if (passwordResolver == null) { password = passwordHint.toCharArray(); } else { try { password = passwordResolver.resolvePassword(passwordHint); } catch (PasswordResolverException e) { throw new SignerException("could not resolve password. Message: " + e.getMessage()); } } } s = keyValues.getValue("keystore"); String keyLabel = keyValues.getValue("key-label"); InputStream keystoreStream; if (StringUtil.startsWithIgnoreCase(s, "base64:")) { keystoreStream = new ByteArrayInputStream(Base64.decode(s.substring("base64:".length()))); } else if (StringUtil.startsWithIgnoreCase(s, "file:")) { String fn = s.substring("file:".length()); try { keystoreStream = new FileInputStream(IoUtil.expandFilepath(fn)); } catch (FileNotFoundException e) { throw new SignerException("file not found: " + fn); } } else { throw new SignerException("unknown keystore content format"); } SoftTokenContentSignerBuilder signerBuilder = new SoftTokenContentSignerBuilder( type, keystoreStream, password, keyLabel, password, certificateChain); try { AlgorithmIdentifier signatureAlgId; if (hashAlgo == null) { signatureAlgId = getSignatureAlgoId(conf); } else { PublicKey pubKey = signerBuilder.getCert().getPublicKey(); signatureAlgId = AlgorithmUtil.getSignatureAlgoId(pubKey, hashAlgo, sigAlgoControl); } return signerBuilder.createSigner(signatureAlgId, parallelism); } catch (OperatorCreationException | NoSuchPaddingException | NoSuchAlgorithmException e) { throw new SignerException(e.getMessage()); } } } else if (StringUtil.startsWithIgnoreCase(type, "java:")) { if (hashAlgo == null) { ConcurrentContentSigner contentSigner; String classname = type.substring("java:".length()); try { Class<?> clazz = Class.forName(classname); contentSigner = (ConcurrentContentSigner) clazz.newInstance(); } catch (Exception e) { throw new SignerException(e.getMessage(), e); } contentSigner.initialize(conf, passwordResolver); if (certificateChain != null) { contentSigner.setCertificateChain(certificateChain); } return contentSigner; } else { throw new SignerException("unknwon type: " + type); } } else { throw new SignerException("unknwon type: " + type); } }