@Override public SecurityInfo add(SecurityInfo info) throws NonUniqueSecurityInfoException { writeLock.lock(); try { String identity = info.getIdentity(); if (identity != null) { SecurityInfo infoByIdentity = securityByIdentity.get(info.getIdentity()); if (infoByIdentity != null && !info.getEndpoint().equals(infoByIdentity.getEndpoint())) { throw new NonUniqueSecurityInfoException("PSK Identity " + info.getIdentity() + " is already used"); } securityByIdentity.put(info.getIdentity(), info); } SecurityInfo previous = securityByEp.put(info.getEndpoint(), info); String previousIdentity = previous == null ? null : previous.getIdentity(); if (previousIdentity != null && !previousIdentity.equals(identity)) { securityByIdentity.remove(previousIdentity); } return previous; } finally { writeLock.unlock(); } }
@Override public byte[] getKey(String identity) { if (securityStore == null) return null; SecurityInfo info = securityStore.getByIdentity(identity); if (info == null || info.getPreSharedKey() == null) { return null; } else { // defensive copy return Arrays.copyOf(info.getPreSharedKey(), info.getPreSharedKey().length); } }
protected boolean checkRpkIdentity(String endpoint, Identity clientIdentity, SecurityInfo securityInfo) { // Manage RPK authentication // ---------------------------------------------------- if (!securityInfo.useRPK()) { LOG.debug("Client '{}' is not supposed to use RPK to authenticate", endpoint); return false; } if (!matchRpkIdenity(endpoint, clientIdentity.getRawPublicKey(), securityInfo.getRawPublicKey())) { return false; } LOG.trace("authenticated client '{}' using DTLS RPK", endpoint); return true; }
protected boolean checkPskIdentity(String endpoint, Identity clientIdentity, SecurityInfo securityInfo) { // Manage PSK authentication // ---------------------------------------------------- if (!securityInfo.usePSK()) { LOG.debug("Client '{}' is not supposed to use PSK to authenticate", endpoint); return false; } if (!matchPskIdentity(endpoint, clientIdentity.getPskIdentity(), securityInfo.getIdentity())) { return false; } LOG.trace("Authenticated client '{}' using DTLS PSK", endpoint); return true; }
JsonObject element = new JsonObject(); element.addProperty("endpoint", src.getEndpoint()); if (src.getIdentity() != null) { JsonObject psk = new JsonObject(); psk.addProperty("identity", src.getIdentity()); psk.addProperty("key", Hex.encodeHexString(src.getPreSharedKey())); element.add("psk", psk); if (src.getRawPublicKey() != null) { JsonObject rpk = new JsonObject(); PublicKey rawPublicKey = src.getRawPublicKey(); if (rawPublicKey instanceof ECPublicKey) { ECPublicKey ecPublicKey = (ECPublicKey) rawPublicKey; if (src.useX509Cert()) { element.addProperty("x509", true);
SecurityInfo securityInfo = SecurityInfo.newPreSharedKeyInfo(endpoint, new String(value.publicKeyOrId, StandardCharsets.UTF_8), value.secretKey); return Arrays.asList(securityInfo); SecurityInfo securityInfo = SecurityInfo.newRawPublicKeyInfo(endpoint, SecurityUtil.publicKey.decode(value.publicKeyOrId)); return Arrays.asList(securityInfo); SecurityInfo securityInfo = SecurityInfo.newX509CertInfo(endpoint); return Arrays.asList(securityInfo);
@Override public SecurityInfo remove(String endpoint) { writeLock.lock(); try { SecurityInfo info = securityByEp.get(endpoint); if (info != null) { if (info.getIdentity() != null) { securityByIdentity.remove(info.getIdentity()); } securityByEp.remove(endpoint); } return info; } finally { writeLock.unlock(); } } }
protected boolean checkX509Identity(String endpoint, Identity clientIdentity, SecurityInfo securityInfo) { // Manage X509 certificate authentication // ---------------------------------------------------- if (!securityInfo.useX509Cert()) { LOG.debug("Client '{}' is not supposed to use X509 certificate to authenticate", endpoint); return false; } if (!matchX509Identity(endpoint, clientIdentity.getX509CommonName(), endpoint)) { return false; } LOG.trace("authenticated client '{}' using DTLS X509 certificates", endpoint); return true; }
/** * {@inheritDoc} */ @Override protected void doPut(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { String[] path = StringUtils.split(req.getPathInfo(), '/'); if (path.length != 1 && "clients".equals(path[0])) { resp.sendError(HttpServletResponse.SC_BAD_REQUEST); return; } try { SecurityInfo info = gsonDes.fromJson(new InputStreamReader(req.getInputStream()), SecurityInfo.class); LOG.debug("New security info for end-point {}: {}", info.getEndpoint(), info); store.add(info); resp.setStatus(HttpServletResponse.SC_OK); } catch (NonUniqueSecurityInfoException e) { LOG.warn("Non unique security info: " + e.getMessage()); resp.setStatus(HttpServletResponse.SC_BAD_REQUEST); resp.getWriter().append(e.getMessage()).flush(); } catch (JsonParseException e) { LOG.warn("Could not parse request body", e); resp.setStatus(HttpServletResponse.SC_BAD_REQUEST); resp.getWriter().append("Invalid request body").flush(); } catch (RuntimeException e) { LOG.warn("unexpected error for request " + req.getPathInfo(), e); resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); } }
@Override public SecurityInfo getByIdentity(String identity) { byte[] identityBytes = identity.getBytes(StandardCharsets.UTF_8); for (Map.Entry<String, BootstrapConfig> e : bsStore.getBootstrapConfigs().entrySet()) { BootstrapConfig bsConfig = e.getValue(); if (bsConfig.security != null) { for (Map.Entry<Integer, BootstrapConfig.ServerSecurity> ec : bsConfig.security.entrySet()) { ServerSecurity serverSecurity = ec.getValue(); if (serverSecurity.bootstrapServer && serverSecurity.securityMode == SecurityMode.PSK && Arrays.equals(serverSecurity.publicKeyOrId, identityBytes)) { return SecurityInfo.newPreSharedKeyInfo(e.getKey(), identity, serverSecurity.secretKey); } } } } return null; }
JsonObject element = new JsonObject(); element.addProperty("endpoint", src.getEndpoint()); if (src.getIdentity() != null) { JsonObject psk = new JsonObject(); psk.addProperty("identity", src.getIdentity()); psk.addProperty("key", Hex.encodeHexString(src.getPreSharedKey())); element.add("psk", psk); if (src.getRawPublicKey() != null) { JsonObject rpk = new JsonObject(); PublicKey rawPublicKey = src.getRawPublicKey(); if (rawPublicKey instanceof ECPublicKey) { ECPublicKey ecPublicKey = (ECPublicKey) rawPublicKey; if (src.useX509Cert()) { element.addProperty("x509", true);
info = SecurityInfo.newPreSharedKeyInfo(endpoint, identity, key); } else if (rpk != null) { PublicKey key; throw new JsonParseException("Invalid security info content", e); info = SecurityInfo.newRawPublicKeyInfo(endpoint, key); } else if (x509 != null && x509.getAsBoolean()) { info = SecurityInfo.newX509CertInfo(endpoint); } else { throw new JsonParseException("Invalid security info content");
@Override public SecurityInfo remove(String endpoint) { try (Jedis j = pool.getResource()) { byte[] data = j.get((SEC_EP + endpoint).getBytes()); if (data != null) { SecurityInfo info = deserialize(data); if (info.getIdentity() != null) { j.hdel(PSKID_SEC.getBytes(), info.getIdentity().getBytes()); } j.del((SEC_EP + endpoint).getBytes()); return info; } } return null; }
public static byte[] serialize(SecurityInfo s) { JsonObject o = Json.object(); o.set("ep", s.getEndpoint()); if (s.getIdentity() != null) { o.set("id", s.getIdentity()); if (s.getPreSharedKey() != null) { o.set("psk", Hex.encodeHexString(s.getPreSharedKey())); if (s.getRawPublicKey() != null) { JsonObject rpk = new JsonObject(); ECPublicKey ecPublicKey = (ECPublicKey) s.getRawPublicKey(); if (s.useX509Cert()) { o.set("x509", true);
public static SecurityInfo deserialize(byte[] data) { JsonObject o = (JsonObject) Json.parse(new String(data)); SecurityInfo i; String ep = o.getString("ep", null); if (o.get("psk") != null) { i = SecurityInfo.newPreSharedKeyInfo(ep, o.getString("id", null), Hex.decodeHex(o.getString("psk", null).toCharArray())); } else if (o.get("x509") != null) { i = SecurityInfo.newX509CertInfo(ep); } else { JsonObject rpk = (JsonObject) o.get("rpk"); PublicKey key; try { byte[] x = Hex.decodeHex(rpk.getString("x", null).toCharArray()); byte[] y = Hex.decodeHex(rpk.getString("y", null).toCharArray()); String params = rpk.getString("params", null); AlgorithmParameters algoParameters = AlgorithmParameters.getInstance("EC"); algoParameters.init(new ECGenParameterSpec(params)); ECParameterSpec parameterSpec = algoParameters.getParameterSpec(ECParameterSpec.class); KeySpec keySpec = new ECPublicKeySpec(new ECPoint(new BigInteger(x), new BigInteger(y)), parameterSpec); key = KeyFactory.getInstance("EC").generatePublic(keySpec); } catch (IllegalArgumentException | InvalidKeySpecException | NoSuchAlgorithmException | InvalidParameterSpecException e) { throw new IllegalStateException("Invalid security info content", e); } i = SecurityInfo.newRawPublicKeyInfo(ep, key); } return i; }
@Override public SecurityInfo add(SecurityInfo info) throws NonUniqueSecurityInfoException { byte[] data = serialize(info); try (Jedis j = pool.getResource()) { if (info.getIdentity() != null) { // populate the secondary index (security info by PSK id) String oldEndpoint = j.hget(PSKID_SEC, info.getIdentity()); if (oldEndpoint != null && !oldEndpoint.equals(info.getEndpoint())) { throw new NonUniqueSecurityInfoException("PSK Identity " + info.getIdentity() + " is already used"); } j.hset(PSKID_SEC.getBytes(), info.getIdentity().getBytes(), info.getEndpoint().getBytes()); } byte[] previousData = j.getSet((SEC_EP + info.getEndpoint()).getBytes(), data); SecurityInfo previous = previousData == null ? null : deserialize(previousData); String previousIdentity = previous == null ? null : previous.getIdentity(); if (previousIdentity != null && !previousIdentity.equals(info.getIdentity())) { j.hdel(PSKID_SEC, previousIdentity); } return previous; } }
@Override public SecurityInfo remove(String endpoint) { try (Jedis j = pool.getResource()) { byte[] data = j.get((SEC_EP + endpoint).getBytes()); if (data != null) { SecurityInfo info = deserialize(data); if (info.getIdentity() != null) { j.hdel(PSKID_SEC.getBytes(), info.getIdentity().getBytes()); } j.del((SEC_EP + endpoint).getBytes()); return info; } } return null; }
@Override public byte[] getKey(String identity) { SecurityInfo info = securityStore.getByIdentity(identity); if (info == null || info.getPreSharedKey() == null) { return null; } else { // defensive copy return Arrays.copyOf(info.getPreSharedKey(), info.getPreSharedKey().length); } }
public static byte[] serialize(SecurityInfo s) { JsonObject o = Json.object(); o.set("ep", s.getEndpoint()); if (s.getIdentity() != null) { o.set("id", s.getIdentity()); if (s.getPreSharedKey() != null) { o.set("psk", Hex.encodeHexString(s.getPreSharedKey())); if (s.getRawPublicKey() != null) { JsonObject rpk = new JsonObject(); ECPublicKey ecPublicKey = (ECPublicKey) s.getRawPublicKey(); if (s.useX509Cert()) { o.set("x509", true);
public static SecurityInfo deserialize(byte[] data) { JsonObject o = (JsonObject) Json.parse(new String(data)); SecurityInfo i; String ep = o.getString("ep", null); if (o.get("psk") != null) { i = SecurityInfo.newPreSharedKeyInfo(ep, o.getString("id", null), Hex.decodeHex(o.getString("psk", null).toCharArray())); } else if (o.get("x509") != null) { i = SecurityInfo.newX509CertInfo(ep); } else { JsonObject rpk = (JsonObject) o.get("rpk"); PublicKey key; try { byte[] x = Hex.decodeHex(rpk.getString("x", null).toCharArray()); byte[] y = Hex.decodeHex(rpk.getString("y", null).toCharArray()); String params = rpk.getString("params", null); AlgorithmParameters algoParameters = AlgorithmParameters.getInstance("EC"); algoParameters.init(new ECGenParameterSpec(params)); ECParameterSpec parameterSpec = algoParameters.getParameterSpec(ECParameterSpec.class); KeySpec keySpec = new ECPublicKeySpec(new ECPoint(new BigInteger(x), new BigInteger(y)), parameterSpec); key = KeyFactory.getInstance("EC").generatePublic(keySpec); } catch (IllegalArgumentException | InvalidKeySpecException | NoSuchAlgorithmException | InvalidParameterSpecException e) { throw new IllegalStateException("Invalid security info content", e); } i = SecurityInfo.newRawPublicKeyInfo(ep, key); } return i; }