@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
Example #2
0
  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 + "'");
    }
  }
Example #3
0
  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;
  }
Example #4
0
 public void setPkcs11ConfFile(final String confFile) {
   if (StringUtil.isBlank(confFile)) {
     this.pkcs11ConfFile = null;
   } else {
     this.pkcs11ConfFile = confFile;
   }
 }
Example #5
0
  @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);
  }
Example #6
0
  @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;
  }
Example #7
0
  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);
    }
  }
Example #8
0
  /*
   * 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);
    }
  }