{"action":"created","comment":{"url":"https://api.github.com/repos/eclipse/californium/pulls/comments/194304526","pull_request_review_id":127448651,"id":194304526,"node_id":"MDI0OlB1bGxSZXF1ZXN0UmV2aWV3Q29tbWVudDE5NDMwNDUyNg==","diff_hunk":"@@ -0,0 +1,557 @@\n+/*******************************************************************************\n+ * Copyright (c) 2018 RISE SICS and others.\n+ * \n+ * All rights reserved. This program and the accompanying materials\n+ * are made available under the terms of the Eclipse Public License v1.0\n+ * and Eclipse Distribution License v1.0 which accompany this distribution.\n+ * \n+ * The Eclipse Public License is available at\n+ *    http://www.eclipse.org/legal/epl-v10.html\n+ * and the Eclipse Distribution License is available at\n+ *    http://www.eclipse.org/org/documents/edl-v10.html.\n+ * \n+ * Contributors:\n+ *    Joakim Brorsson\n+ *    Ludwig Seitz (RISE SICS)\n+ *    Tobias Andersson (RISE SICS)\n+ *    \n+ ******************************************************************************/\n+package org.eclipse.californium.oscore;\n+\n+import java.nio.ByteBuffer;\n+import java.util.ArrayList;\n+import java.util.List;\n+import java.util.logging.Logger;\n+\n+import org.eclipse.californium.core.coap.CoAP;\n+import org.eclipse.californium.core.coap.Option;\n+import org.eclipse.californium.core.coap.OptionSet;\n+import org.eclipse.californium.elements.util.DatagramReader;\n+import org.eclipse.californium.elements.util.DatagramWriter;\n+\n+import com.upokecenter.cbor.CBORObject;\n+\n+public class OSSerializer {\n+\n+\t/**\n+\t * The logger\n+\t */\n+\tprivate static final Logger LOGGER = Logger.getLogger(OSSerializer.class.getName());\n+\n+\t/**\n+\t * Prepare options and payload for encrypting.\n+\t * \n+\t * @param options the options\n+\t * \n+\t * @param payload the payload\n+\t * \n+\t * @return the serialized plaintext for OSCore\n+\t */\n+\tpublic static byte[] serializeConfidentialData(OptionSet options, byte[] payload, int realCode) {\n+\t\tif (options != null) {\n+\t\t\tif (realCode > 0) {\n+\t\t\t\tDatagramWriter writer = new DatagramWriter();\n+\t\t\t\twriteOptions(writer, options, true, false, realCode);\n+\t\t\t\tif (payload != null && payload.length > 0) {\n+\t\t\t\t\twritePayload(writer, payload);\n+\t\t\t\t}\n+\t\t\t\treturn writer.toByteArray();\n+\t\t\t} else {\n+\t\t\t\tLOGGER.severe(OSExceptionHandler.COAP_CODE_INVALID);\n+\t\t\t\tthrow new IllegalArgumentException(OSExceptionHandler.COAP_CODE_INVALID);\n+\t\t\t}\n+\t\t} else {\n+\t\t\tLOGGER.severe(OSExceptionHandler.OPTIONSET_NULL);\n+\t\t\tthrow new IllegalArgumentException(OSExceptionHandler.OPTIONSET_NULL);\n+\t\t}\n+\t}\n+\n+\t/**\n+\t * Prepare the additional authenticated data of a response to be sent.\n+\t * \n+\t * external_aad = [ ver : uint, alg : int, request_kid :\n+\t * bstr, request_seq : bstr, options : bstr]\n+\t * \n+\t * @param version the CoAP version number\n+\t * @param ctx the OSCore context\n+\t * @param options the option set\n+\t * \n+\t * @return the serialized AAD for OSCore\n+\t */\n+\tpublic static byte[] serializeSendResponseAAD(int version, OSCoreCtx ctx, OptionSet options, boolean newPartialIV) {\n+\t\tif (version == CoAP.VERSION) {\n+\t\t\tif (ctx != null) {\n+\t\t\t\tif (options != null) {\n+\t\t\t\t\tCBORObject algorithms = CBORObject.NewArray();\n+\t\t\t\t\talgorithms.Add(ctx.getAlg().AsCBOR());\n+\n+\t\t\t\t\tCBORObject aad = CBORObject.NewArray();\n+\t\t\t\t\taad.Add(version);\n+\t\t\t\t\taad.Add(algorithms);\n+\t\t\t\t\taad.Add(ctx.getRecipientId());\n+\n+\t\t\t\t\tif (newPartialIV) {\n+\t\t\t\t\t\taad.Add(processPartialIV(ctx.getSenderSeq()));\n+\t\t\t\t\t} else {\n+\t\t\t\t\t\taad.Add(processPartialIV(ctx.getReceiverSeq()));\n+\t\t\t\t\t}\n+\n+\t\t\t\t\treturn aad.EncodeToBytes();\n+\t\t\t\t} else {\n+\t\t\t\t\tLOGGER.severe(OSExceptionHandler.OPTIONSET_NULL);\n+\t\t\t\t\tthrow new IllegalArgumentException(OSExceptionHandler.OPTIONSET_NULL);\n+\t\t\t\t}\n+\t\t\t} else {\n+\t\t\t\tLOGGER.severe(OSExceptionHandler.CTX_NULL);\n+\t\t\t\tthrow new IllegalArgumentException(OSExceptionHandler.CTX_NULL);\n+\t\t\t}\n+\t\t} else {\n+\t\t\tLOGGER.severe(OSExceptionHandler.WRONG_VERSION_NBR);\n+\t\t\tthrow new IllegalArgumentException(OSExceptionHandler.WRONG_VERSION_NBR);\n+\t\t}\n+\t}\n+\n+\t/**\n+\t * Prepare the additional authenticated data of a received response.\n+\t * \n+\t * external_aad = [ ver : uint, alg : int, request_kid :\n+\t * bstr, request_seq : bstr, options : bstr]\n+\t * \n+\t * @param version the CoAP version number\n+\t * @param seq the sequence number\n+\t * @param ctx the OSCore context\n+\t * @param options the option set\n+\t * \n+\t * @return the serialized AAD for OSCore\n+\t */\n+\tpublic static byte[] serializeReceiveResponseAAD(int version, int seq, OSCoreCtx ctx, OptionSet options) {\n+\t\tif (version == CoAP.VERSION) {\n+\t\t\tif (seq > -1) {\n+\t\t\t\tif (ctx != null) {\n+\t\t\t\t\tif (options != null) {\n+\t\t\t\t\t\tCBORObject algorithms = CBORObject.NewArray();\n+\t\t\t\t\t\talgorithms.Add(ctx.getAlg().AsCBOR());\n+\n+\t\t\t\t\t\tCBORObject aad = CBORObject.NewArray();\n+\t\t\t\t\t\taad.Add(version);\n+\t\t\t\t\t\taad.Add(algorithms);\n+\t\t\t\t\t\taad.Add(ctx.getSenderId());\n+\t\t\t\t\t\taad.Add(processPartialIV(seq));\n+\t\t\t\t\t\treturn aad.EncodeToBytes();\n+\t\t\t\t\t} else {\n+\t\t\t\t\t\tLOGGER.severe(OSExceptionHandler.OPTIONSET_NULL);\n+\t\t\t\t\t\tthrow new IllegalArgumentException(OSExceptionHandler.OPTIONSET_NULL);\n+\t\t\t\t\t}\n+\t\t\t\t} else {\n+\t\t\t\t\tLOGGER.severe(OSExceptionHandler.CTX_NULL);\n+\t\t\t\t\tthrow new IllegalArgumentException(OSExceptionHandler.CTX_NULL);\n+\t\t\t\t}\n+\t\t\t} else {\n+\t\t\t\tLOGGER.severe(OSExceptionHandler.SEQ_NBR_INVALID);\n+\t\t\t\tthrow new IllegalArgumentException(OSExceptionHandler.SEQ_NBR_INVALID);\n+\t\t\t}\n+\t\t} else {\n+\t\t\tLOGGER.severe(OSExceptionHandler.WRONG_VERSION_NBR);\n+\t\t\tthrow new IllegalArgumentException(OSExceptionHandler.WRONG_VERSION_NBR);\n+\t\t}\n+\t}\n+\n+\t/**\n+\t * Prepare the additional authenticated data of a request to be sent.\n+\t * \n+\t * external_aad = [ ver : uint, alg : int, request_kid :\n+\t * bstr, request_seq : bstr, options : bstr]\n+\t * \n+\t * @param version the CoAP version number\n+\t * @param ctx the OSCore context@param code\n+\t * @param options the option set\n+\t * \n+\t *\n+\t * @return the serialized AAD for OSCore\n+\t */\n+\tpublic static byte[] serializeSendRequestAAD(int version, OSCoreCtx ctx, OptionSet options) {\n+\t\tif (version == CoAP.VERSION) {\n+\t\t\tif (ctx != null) {\n+\t\t\t\tif (options != null) {\n+\t\t\t\t\tCBORObject algorithms = CBORObject.NewArray();\n+\t\t\t\t\talgorithms.Add(ctx.getAlg().AsCBOR());\n+\n+\t\t\t\t\tCBORObject aad = CBORObject.NewArray();\n+\t\t\t\t\taad.Add(version);\n+\t\t\t\t\taad.Add(algorithms);\n+\t\t\t\t\taad.Add(ctx.getSenderId());\n+\t\t\t\t\taad.Add(processPartialIV(ctx.getSenderSeq()));\n+\t\t\t\t\treturn aad.EncodeToBytes();\n+\t\t\t\t} else {\n+\t\t\t\t\tLOGGER.severe(OSExceptionHandler.OPTIONSET_NULL);\n+\t\t\t\t\tthrow new IllegalArgumentException(OSExceptionHandler.OPTIONSET_NULL);\n+\t\t\t\t}\n+\t\t\t} else {\n+\t\t\t\tLOGGER.severe(OSExceptionHandler.CTX_NULL);\n+\t\t\t\tthrow new IllegalArgumentException(OSExceptionHandler.CTX_NULL);\n+\t\t\t}\n+\t\t} else {\n+\t\t\tLOGGER.severe(OSExceptionHandler.WRONG_VERSION_NBR);\n+\t\t\tthrow new IllegalArgumentException(OSExceptionHandler.WRONG_VERSION_NBR);\n+\t\t}\n+\t}\n+\n+\t/**\n+\t * Prepare the additional authenticated data of a received request.\n+\t * \n+\t * external_aad = [ ver : uint, alg : int, request_kid :\n+\t * bstr, request_seq : bstr, options : bstr]\n+\t * \n+\t * @param version the CoAP version number\n+\t * @param seq the sent sequence number\n+\t * @param ctx the OSCore context@param code\n+\t * @param options the option set\n+\t * \n+\t *\n+\t * @return the serialized AAD for OSCore\n+\t */\n+\tpublic static byte[] serializeReceiveRequestAAD(int version, int seq, OSCoreCtx ctx, OptionSet options) {\n+\t\tif (version == CoAP.VERSION) {\n+\t\t\tif (seq > -1) {\n+\t\t\t\tif (ctx != null) {\n+\t\t\t\t\tif (options != null) {\n+\t\t\t\t\t\tCBORObject algorithms = CBORObject.NewArray();\n+\t\t\t\t\t\talgorithms.Add(ctx.getAlg().AsCBOR());\n+\n+\t\t\t\t\t\tCBORObject aad = CBORObject.NewArray();\n+\t\t\t\t\t\taad.Add(version);\n+\t\t\t\t\t\taad.Add(algorithms);\n+\t\t\t\t\t\taad.Add(ctx.getRecipientId());\n+\t\t\t\t\t\taad.Add(processPartialIV(seq));\n+\t\t\t\t\t\treturn aad.EncodeToBytes();\n+\t\t\t\t\t} else {\n+\t\t\t\t\t\tLOGGER.severe(OSExceptionHandler.OPTIONSET_NULL);\n+\t\t\t\t\t\tthrow new IllegalArgumentException(OSExceptionHandler.OPTIONSET_NULL);\n+\t\t\t\t\t}\n+\t\t\t\t} else {\n+\t\t\t\t\tLOGGER.severe(OSExceptionHandler.CTX_NULL);\n+\t\t\t\t\tthrow new IllegalArgumentException(OSExceptionHandler.CTX_NULL);\n+\t\t\t\t}\n+\t\t\t} else {\n+\t\t\t\tLOGGER.severe(OSExceptionHandler.SEQ_NBR_INVALID);\n+\t\t\t\tthrow new IllegalArgumentException(OSExceptionHandler.SEQ_NBR_INVALID);\n+\t\t\t}\n+\t\t} else {\n+\t\t\tLOGGER.severe(OSExceptionHandler.WRONG_VERSION_NBR);\n+\t\t\tthrow new IllegalArgumentException(OSExceptionHandler.WRONG_VERSION_NBR);\n+\t\t}\n+\t}\n+\n+\t/**\n+\t * Prepare the E or I options for encrypting.\n+\t * \n+\t * @param writer the datagram writer collecting the necessary bytes\n+\t * @param optionSet the original options\n+\t * @param isConfidential true will use E options since we are serializing confidential data, false will use I options\n+\t * @param request true is request processing, false is response processing\n+\t * @param realCode the real code\n+\t */\n+\tprivate static void writeOptions(DatagramWriter writer, OptionSet optionSet, boolean isConfidential, boolean request,\n+\t\t\tint realCode) {\n+\t\tint previousOptionNumber = 0;\n+\n+\t\tOptionSet filteredOptions = null;\n+\t\tif (isConfidential) {\n+\t\t\tfilteredOptions = OptionJuggle.prepareEoptions(optionSet);\n+\t\t}\n+\n+\t\tif (realCode > 0) {\n+\t\t\twriter.writeBytes(new byte[] { (byte) realCode });\n+\t\t}\n+\n+\t\tfor (Option option : filteredOptions.asSortedList()) {\n+\n+\t\t\t// write 4-bit option delta\n+\t\t\tint optionDelta = option.getNumber() - previousOptionNumber;\n+\t\t\tint optionDeltaNibble = getOptionNibble(optionDelta);\n+\t\t\twriter.write(optionDeltaNibble, CoAP.MessageFormat.OPTION_DELTA_BITS);\n+\n+\t\t\t// write 4-bit option length\n+\t\t\tint optionLength = option.getLength();\n+\t\t\tint optionLengthNibble = getOptionNibble(optionLength);\n+\t\t\twriter.write(optionLengthNibble, CoAP.MessageFormat.OPTION_LENGTH_BITS);\n+\n+\t\t\t// write extended option delta field (0 - 2 bytes)\n+\t\t\tif (optionDeltaNibble == 13) {\n+\t\t\t\twriter.write(optionDelta - 13, 8);\n+\t\t\t} else if (optionDeltaNibble == 14) {\n+\t\t\t\twriter.write(optionDelta - 269, 16);\n+\t\t\t}\n+\n+\t\t\t// write extended option length field (0 - 2 bytes)\n+\t\t\tif (optionLengthNibble == 13) {\n+\t\t\t\twriter.write(optionLength - 13, 8);\n+\t\t\t} else if (optionLengthNibble == 14) {\n+\t\t\t\twriter.write(optionLength - 269, 16);\n+\t\t\t}\n+\n+\t\t\t// write option value\n+\t\t\twriter.writeBytes(option.getValue());\n+\n+\t\t\t// update last option number\n+\t\t\tpreviousOptionNumber = option.getNumber();\n+\t\t}\n+\t}\n+\n+\t/**\n+\t * Read the E options from an OSCore plaintext (decrypted).\n+\t * \n+\t * @param plaintext the OSCore plaintext\n+\t * \n+\t * @return the list of E options\n+\t */\n+\tpublic static List<Option> readConfidentialOptions(byte[] plaintext) {\n+\t\tif (plaintext != null) {\n+\t\t\tDatagramReader reader = new DatagramReader(plaintext);\n+\t\t\tList<Option> optionList = new ArrayList<>();\n+\t\t\tint currentOption = 0;\n+\t\t\tbyte nextByte = 0;\n+\t\t\twhile (reader.bytesAvailable()) {\n+\t\t\t\tnextByte = reader.readNextByte();\n+\t\t\t\tif (nextByte != CoAP.MessageFormat.PAYLOAD_MARKER) {\n+\t\t\t\t\t// the first 4 bits of the byte represent the option delta\n+\t\t\t\t\tint optionDeltaNibble = (0xF0 & nextByte) >> 4;\n+\t\t\t\t\tcurrentOption += readOptionValueFromNibble(reader, optionDeltaNibble);\n+\n+\t\t\t\t\t// the second 4 bits represent the option length\n+\t\t\t\t\tint optionLengthNibble = (0x0F & nextByte);\n+\t\t\t\t\tint optionLength = readOptionValueFromNibble(reader, optionLengthNibble);\n+\n+\t\t\t\t\t// read option\n+\t\t\t\t\tOption option = new Option(currentOption);\n+\t\t\t\t\toption.setValue(reader.readBytes(optionLength));\n+\n+\t\t\t\t\t// add option to message\n+\t\t\t\t\toptionList.add(option);\n+\t\t\t\t} else\n+\t\t\t\t\tbreak;\n+\t\t\t}\n+\t\t\treturn optionList;\n+\t\t} else {\n+\t\t\tLOGGER.severe(OSExceptionHandler.BYTE_ARRAY_NULL);\n+\t\t\tthrow new IllegalArgumentException(OSExceptionHandler.BYTE_ARRAY_NULL);\n+\t\t}\n+\t}\n+\n+\t/**\n+\t * Read the payload from an OSCore plaintext (decrypted), if any.\n+\t * \n+\t * @param plaintext the OSCore plaintext\n+\t * \n+\t * @return the payload or null if there is none\n+\t * @throws OSException if the payload marker is present and the payload is\n+\t *             zero length\n+\t */\n+\tpublic static byte[] readPayload(byte[] plaintext) throws OSException {\n+\t\tif (plaintext != null) {\n+\t\t\tDatagramReader reader = new DatagramReader(plaintext);\n+\t\t\tbyte nextByte = 0;\n+\t\t\twhile (reader.bytesAvailable()) {\n+\t\t\t\tnextByte = reader.readNextByte();\n+\t\t\t\tif (nextByte == CoAP.MessageFormat.PAYLOAD_MARKER) {\n+\t\t\t\t\t// the presence of a marker followed by a zero-length\n+\t\t\t\t\t// payload\n+\t\t\t\t\t// must be processed as a message format error\n+\t\t\t\t\tif (!reader.bytesAvailable()) {\n+\t\t\t\t\t\tLOGGER.severe(\"Payload marker found with zero-length payload\");\n+\t\t\t\t\t\tthrow new OSException(\"Illegal payload marker\");\n+\t\t\t\t\t}\n+\t\t\t\t\treturn reader.readBytesLeft();\n+\t\t\t\t}\n+\t\t\t}\n+\t\t\treturn new byte[0];\n+\t\t} else {\n+\t\t\tLOGGER.severe(OSExceptionHandler.BYTE_ARRAY_NULL);\n+\t\t\tthrow new IllegalArgumentException(OSExceptionHandler.BYTE_ARRAY_NULL);\n+\t\t}\n+\t}\n+\n+\t/**\n+\t * Write the payload to the DatagramWriter.\n+\t * \n+\t * @param writer the DatagramWriter\n+\t * @param payload the payload\n+\t */\n+\tprivate static void writePayload(DatagramWriter writer, byte[] payload) {\n+\t\tif (payload != null && payload.length > 0) {\n+\t\t\t// if payload is present and of non-zero length, it is prefixed by\n+\t\t\t// an one-byte Payload Marker (0xFF) which indicates the end of\n+\t\t\t// options and the start of the payload\n+\t\t\twriter.writeByte(CoAP.MessageFormat.PAYLOAD_MARKER);\n+\t\t\twriter.writeBytes(payload);\n+\t\t}\n+\t}\n+\n+\t/**\n+\t * Returns the 4-bit option header value.\n+\t *\n+\t * @param optionValue the option value (delta or length) to be encoded.\n+\t * @return the 4-bit option header value.\n+\t */\n+\tprivate static int getOptionNibble(int optionValue) {\n+\t\tif (optionValue <= 12) {\n+\t\t\treturn optionValue;\n+\t\t} else if (optionValue <= 255 + 13) {\n+\t\t\treturn 13;\n+\t\t} else if (optionValue <= 65535 + 269) {\n+\t\t\treturn 14;\n+\t\t} else {\n+\t\t\tthrow new IllegalArgumentException(\"Unsupported option delta \" + optionValue);\n+\t\t}\n+\t}\n+\n+\t/**\n+\t * Calculates the value used in the extended option fields as specified in\n+\t * RFC 7252, Section 3.1\n+\t *\n+\t * @param nibble the 4-bit option header value.\n+\t * @return the value calculated from the nibble and the extended option\n+\t *         value.\n+\t */\n+\tprivate static int readOptionValueFromNibble(DatagramReader reader, int nibble) {\n+\t\tif (nibble <= 12) {\n+\t\t\treturn nibble;\n+\t\t} else if (nibble == 13) {\n+\t\t\treturn reader.read(8) + 13;\n+\t\t} else if (nibble == 14) {\n+\t\t\treturn reader.read(16) + 269;\n+\t\t} else {\n+\t\t\tthrow new IllegalArgumentException(\"Unsupported option delta \" + nibble);\n+\t\t}\n+\t}\n+\n+\t/**\n+\t * Generates the nonce.\n+\t * \n+\t * @param partialIV\n+\t * @param senderID\n+\t * @param commonIV\n+\t * @param nonceLength the algorithm dependent length of nonce\n+\t * @return the generated nonce or null if either one of the input parameters\n+\t *         are null\n+\t * @throws OSException if any of the parameters are unvalid\n+\t */\n+\tpublic static byte[] nonceGeneration(byte[] partialIV, byte[] senderID, byte[] commonIV, int nonceLength)\n+\t\t\tthrows OSException {\n+\t\tif (partialIV != null) {\n+\t\t\tif (senderID != null) {\n+\t\t\t\tif (commonIV != null) {\n+\t\t\t\t\tif (nonceLength > 0) {\n+\t\t\t\t\t\tint s = senderID.length;\n+\t\t\t\t\t\tint zeroes = 5 - partialIV.length;\n+\n+\t\t\t\t\t\tif (zeroes > 0) {\n+\t\t\t\t\t\t\tpartialIV = leftPaddingZeroes(partialIV, zeroes);\n+\t\t\t\t\t\t}\n+\n+\t\t\t\t\t\tzeroes = (nonceLength - 6) - senderID.length;\n+\n+\t\t\t\t\t\tif (zeroes > 0) {\n+\t\t\t\t\t\t\tsenderID = leftPaddingZeroes(senderID, zeroes);\n+\t\t\t\t\t\t}\n+\n+\t\t\t\t\t\tzeroes = nonceLength - commonIV.length;\n+\n+\t\t\t\t\t\tif (zeroes > 0) {\n+\t\t\t\t\t\t\tcommonIV = leftPaddingZeroes(commonIV, zeroes);\n+\t\t\t\t\t\t}\n+\n+\t\t\t\t\t\tbyte[] tmp = new byte[1 + senderID.length + partialIV.length];\n+\t\t\t\t\t\ttmp[0] = (byte) s;\n+\t\t\t\t\t\tSystem.arraycopy(senderID, 0, tmp, 1, senderID.length);\n+\t\t\t\t\t\tSystem.arraycopy(partialIV, 0, tmp, senderID.length + 1, partialIV.length);\n+\n+\t\t\t\t\t\tbyte[] result = new byte[commonIV.length];\n+\n+\t\t\t\t\t\tint i = 0;\n+\t\t\t\t\t\tfor (byte b : tmp) {\n+\t\t\t\t\t\t\tresult[i] = (byte) (b ^ commonIV[i++]);\n+\t\t\t\t\t\t}\n+\n+\t\t\t\t\t\treturn result;\n+\t\t\t\t\t} else {\n+\t\t\t\t\t\tLOGGER.severe(OSExceptionHandler.NONCE_LENGTH_INVALID);\n+\t\t\t\t\t\tthrow new IllegalArgumentException(OSExceptionHandler.NONCE_LENGTH_INVALID);\n+\t\t\t\t\t}\n+\t\t\t\t} else {\n+\t\t\t\t\tLOGGER.severe(OSExceptionHandler.COMMON_IV_NULL);\n+\t\t\t\t\tthrow new IllegalArgumentException(OSExceptionHandler.COMMON_IV_NULL);\n+\t\t\t\t}\n+\t\t\t} else {\n+\t\t\t\tLOGGER.severe(OSExceptionHandler.SENDER_ID_NULL);\n+\t\t\t\tthrow new IllegalArgumentException(OSExceptionHandler.SENDER_ID_NULL);\n+\t\t\t}\n+\t\t} else {\n+\t\t\tLOGGER.severe(OSExceptionHandler.PARTIAL_IV_NULL);\n+\t\t\tthrow new IllegalArgumentException(OSExceptionHandler.PARTIAL_IV_NULL);\n+\t\t}\n+\t}\n+\t\n+\t/**\n+\t * Padds the left side of the byte array paddMe with zeroes as the int\n+\t * zeroes has\n+\t * \n+\t * @param paddMe\n+\t * @param zeroes\n+\t * @return\n+\t */\n+\tprivate static byte[] leftPaddingZeroes(byte[] paddMe, int zeroes) {\n+\t\tbyte[] insert = new byte[zeroes];\n+\t\tfor (int i = 0; i > zeroes; i++) {\n+\t\t\tinsert[i] = 0x00;\n+\t\t}\n+\t\tbyte[] tmp = new byte[zeroes + paddMe.length];\n+\t\tSystem.arraycopy(insert, 0, tmp, 0, insert.length);\n+\t\tSystem.arraycopy(paddMe, 0, tmp, insert.length, paddMe.length);\n+\t\treturn tmp;\n+\t}\n+\t\n+\t/**\n+\t * Processes a partialIV correctly\n+\t * \n+\t * @param partialIV the partialIV\n+\t * @return the processed partialIV\n+\t */\n+\tpublic static byte[] processPartialIV(int value) {\n+\t\tbyte[] partialIV = ByteBuffer.allocate(Integer.BYTES).putInt(value).array();\n+\t\treturn stripZeroes(partialIV);\n+\t}\n+\t\n+\t/**\n+\t * Remove trailing zeroes in a byte array\n+\t * \n+\t * @param in the incoming array\n+\t * @return the array with trailing zeroes removed\n+\t */\n+\tpublic static byte[] stripZeroes(byte[] in) {\n+\t\tif (in != null) {\n+\t\t\tif (in.length == 1)\n+\t\t\t\treturn in;\n+\t\t\tint firstValue = 0;\n+\n+\t\t\twhile (firstValue < in.length && in[firstValue] == 0) {\n+\t\t\t\tfirstValue++;\n+\t\t\t}\n+\n+\t\t\tbyte[] out = new byte[in.length - firstValue];\n+\t\t\tfor (int i = 0; i < out.length; i++) {\n+\t\t\t\tout[i] = in[firstValue + i];\n+\t\t\t}\n+\n+\t\t\tif (out.length == 0) {\n+\t\t\t\tbyte[] res = new byte[1];\n+\t\t\t\tres[0] = (byte) 0x00;\n+\t\t\t\tout = res.clone();","path":"oscore-cf/src/main/java/org/eclipse/californium/oscore/OSSerializer.java","position":549,"original_position":549,"commit_id":"36b04709d1878eebd88dfb4f8805cdc0ebcb7d15","original_commit_id":"36b04709d1878eebd88dfb4f8805cdc0ebcb7d15","user":{"login":"T0bbe","id":1225360,"node_id":"MDQ6VXNlcjEyMjUzNjA=","avatar_url":"https://avatars0.githubusercontent.com/u/1225360?v=4","gravatar_id":"","url":"https://api.github.com/users/T0bbe","html_url":"https://github.com/T0bbe","followers_url":"https://api.github.com/users/T0bbe/followers","following_url":"https://api.github.com/users/T0bbe/following{/other_user}","gists_url":"https://api.github.com/users/T0bbe/gists{/gist_id}","starred_url":"https://api.github.com/users/T0bbe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/T0bbe/subscriptions","organizations_url":"https://api.github.com/users/T0bbe/orgs","repos_url":"https://api.github.com/users/T0bbe/repos","events_url":"https://api.github.com/users/T0bbe/events{/privacy}","received_events_url":"https://api.github.com/users/T0bbe/received_events","type":"User","site_admin":false},"body":"Good point!","created_at":"2018-06-11T06:50:10Z","updated_at":"2018-06-11T06:50:11Z","html_url":"https://github.com/eclipse/californium/pull/650#discussion_r194304526","pull_request_url":"https://api.github.com/repos/eclipse/californium/pulls/650","author_association":"NONE","_links":{"self":{"href":"https://api.github.com/repos/eclipse/californium/pulls/comments/194304526"},"html":{"href":"https://github.com/eclipse/californium/pull/650#discussion_r194304526"},"pull_request":{"href":"https://api.github.com/repos/eclipse/californium/pulls/650"}},"in_reply_to_id":194066962},"pull_request":{"url":"https://api.github.com/repos/eclipse/californium/pulls/650","id":191440440,"node_id":"MDExOlB1bGxSZXF1ZXN0MTkxNDQwNDQw","html_url":"https://github.com/eclipse/californium/pull/650","diff_url":"https://github.com/eclipse/californium/pull/650.diff","patch_url":"https://github.com/eclipse/californium/pull/650.patch","issue_url":"https://api.github.com/repos/eclipse/californium/issues/650","number":650,"state":"open","locked":false,"title":"Basic OSCORE","user":{"login":"T0bbe","id":1225360,"node_id":"MDQ6VXNlcjEyMjUzNjA=","avatar_url":"https://avatars0.githubusercontent.com/u/1225360?v=4","gravatar_id":"","url":"https://api.github.com/users/T0bbe","html_url":"https://github.com/T0bbe","followers_url":"https://api.github.com/users/T0bbe/followers","following_url":"https://api.github.com/users/T0bbe/following{/other_user}","gists_url":"https://api.github.com/users/T0bbe/gists{/gist_id}","starred_url":"https://api.github.com/users/T0bbe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/T0bbe/subscriptions","organizations_url":"https://api.github.com/users/T0bbe/orgs","repos_url":"https://api.github.com/users/T0bbe/repos","events_url":"https://api.github.com/users/T0bbe/events{/privacy}","received_events_url":"https://api.github.com/users/T0bbe/received_events","type":"User","site_admin":false},"body":"This code provides the basic OSCORE functionality, which means that the support for Observe and Blockwise are not included in this PR.\r\n\r\nSee draft OSCORE [1] for additional details.\r\n\r\n[1] https://github.com/core-wg/oscoap\r\n","created_at":"2018-05-30T12:46:43Z","updated_at":"2018-06-11T06:50:11Z","closed_at":null,"merged_at":null,"merge_commit_sha":"02ab80cae2fa2d5e4b9677940c7795cfe7956005","assignee":null,"assignees":[],"requested_reviewers":[],"requested_teams":[],"labels":[],"milestone":null,"commits_url":"https://api.github.com/repos/eclipse/californium/pulls/650/commits","review_comments_url":"https://api.github.com/repos/eclipse/californium/pulls/650/comments","review_comment_url":"https://api.github.com/repos/eclipse/californium/pulls/comments{/number}","comments_url":"https://api.github.com/repos/eclipse/californium/issues/650/comments","statuses_url":"https://api.github.com/repos/eclipse/californium/statuses/36b04709d1878eebd88dfb4f8805cdc0ebcb7d15","head":{"label":"T0bbe:basic_oscore","ref":"basic_oscore","sha":"36b04709d1878eebd88dfb4f8805cdc0ebcb7d15","user":{"login":"T0bbe","id":1225360,"node_id":"MDQ6VXNlcjEyMjUzNjA=","avatar_url":"https://avatars0.githubusercontent.com/u/1225360?v=4","gravatar_id":"","url":"https://api.github.com/users/T0bbe","html_url":"https://github.com/T0bbe","followers_url":"https://api.github.com/users/T0bbe/followers","following_url":"https://api.github.com/users/T0bbe/following{/other_user}","gists_url":"https://api.github.com/users/T0bbe/gists{/gist_id}","starred_url":"https://api.github.com/users/T0bbe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/T0bbe/subscriptions","organizations_url":"https://api.github.com/users/T0bbe/orgs","repos_url":"https://api.github.com/users/T0bbe/repos","events_url":"https://api.github.com/users/T0bbe/events{/privacy}","received_events_url":"https://api.github.com/users/T0bbe/received_events","type":"User","site_admin":false},"repo":{"id":128070054,"node_id":"MDEwOlJlcG9zaXRvcnkxMjgwNzAwNTQ=","name":"californium","full_name":"T0bbe/californium","owner":{"login":"T0bbe","id":1225360,"node_id":"MDQ6VXNlcjEyMjUzNjA=","avatar_url":"https://avatars0.githubusercontent.com/u/1225360?v=4","gravatar_id":"","url":"https://api.github.com/users/T0bbe","html_url":"https://github.com/T0bbe","followers_url":"https://api.github.com/users/T0bbe/followers","following_url":"https://api.github.com/users/T0bbe/following{/other_user}","gists_url":"https://api.github.com/users/T0bbe/gists{/gist_id}","starred_url":"https://api.github.com/users/T0bbe/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/T0bbe/subscriptions","organizations_url":"https://api.github.com/users/T0bbe/orgs","repos_url":"https://api.github.com/users/T0bbe/repos","events_url":"https://api.github.com/users/T0bbe/events{/privacy}","received_events_url":"https://api.github.com/users/T0bbe/received_events","type":"User","site_admin":false},"private":false,"html_url":"https://github.com/T0bbe/californium","description":null,"fork":true,"url":"https://api.github.com/repos/T0bbe/californium","forks_url":"https://api.github.com/repos/T0bbe/californium/forks","keys_url":"https://api.github.com/repos/T0bbe/californium/keys{/key_id}","collaborators_url":"https://api.github.com/repos/T0bbe/californium/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/T0bbe/californium/teams","hooks_url":"https://api.github.com/repos/T0bbe/californium/hooks","issue_events_url":"https://api.github.com/repos/T0bbe/californium/issues/events{/number}","events_url":"https://api.github.com/repos/T0bbe/californium/events","assignees_url":"https://api.github.com/repos/T0bbe/californium/assignees{/user}","branches_url":"https://api.github.com/repos/T0bbe/californium/branches{/branch}","tags_url":"https://api.github.com/repos/T0bbe/californium/tags","blobs_url":"https://api.github.com/repos/T0bbe/californium/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/T0bbe/californium/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/T0bbe/californium/git/refs{/sha}","trees_url":"https://api.github.com/repos/T0bbe/californium/git/trees{/sha}","statuses_url":"https://api.github.com/repos/T0bbe/californium/statuses/{sha}","languages_url":"https://api.github.com/repos/T0bbe/californium/languages","stargazers_url":"https://api.github.com/repos/T0bbe/californium/stargazers","contributors_url":"https://api.github.com/repos/T0bbe/californium/contributors","subscribers_url":"https://api.github.com/repos/T0bbe/californium/subscribers","subscription_url":"https://api.github.com/repos/T0bbe/californium/subscription","commits_url":"https://api.github.com/repos/T0bbe/californium/commits{/sha}","git_commits_url":"https://api.github.com/repos/T0bbe/californium/git/commits{/sha}","comments_url":"https://api.github.com/repos/T0bbe/californium/comments{/number}","issue_comment_url":"https://api.github.com/repos/T0bbe/californium/issues/comments{/number}","contents_url":"https://api.github.com/repos/T0bbe/californium/contents/{+path}","compare_url":"https://api.github.com/repos/T0bbe/californium/compare/{base}...{head}","merges_url":"https://api.github.com/repos/T0bbe/californium/merges","archive_url":"https://api.github.com/repos/T0bbe/californium/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/T0bbe/californium/downloads","issues_url":"https://api.github.com/repos/T0bbe/californium/issues{/number}","pulls_url":"https://api.github.com/repos/T0bbe/californium/pulls{/number}","milestones_url":"https://api.github.com/repos/T0bbe/californium/milestones{/number}","notifications_url":"https://api.github.com/repos/T0bbe/californium/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/T0bbe/californium/labels{/name}","releases_url":"https://api.github.com/repos/T0bbe/californium/releases{/id}","deployments_url":"https://api.github.com/repos/T0bbe/californium/deployments","created_at":"2018-04-04T13:58:39Z","updated_at":"2018-04-04T13:58:43Z","pushed_at":"2018-05-30T12:17:56Z","git_url":"git://github.com/T0bbe/californium.git","ssh_url":"git@github.com:T0bbe/californium.git","clone_url":"https://github.com/T0bbe/californium.git","svn_url":"https://github.com/T0bbe/californium","homepage":null,"size":6981,"stargazers_count":0,"watchers_count":0,"language":"Java","has_issues":false,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":0,"mirror_url":null,"archived":false,"open_issues_count":0,"license":{"key":"other","name":"Other","spdx_id":null,"url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":0,"open_issues":0,"watchers":0,"default_branch":"master"}},"base":{"label":"eclipse:2.0.x","ref":"2.0.x","sha":"4c182c48d5905d389b8a84adf3a16aa02e98e369","user":{"login":"eclipse","id":56974,"node_id":"MDEyOk9yZ2FuaXphdGlvbjU2OTc0","avatar_url":"https://avatars1.githubusercontent.com/u/56974?v=4","gravatar_id":"","url":"https://api.github.com/users/eclipse","html_url":"https://github.com/eclipse","followers_url":"https://api.github.com/users/eclipse/followers","following_url":"https://api.github.com/users/eclipse/following{/other_user}","gists_url":"https://api.github.com/users/eclipse/gists{/gist_id}","starred_url":"https://api.github.com/users/eclipse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/eclipse/subscriptions","organizations_url":"https://api.github.com/users/eclipse/orgs","repos_url":"https://api.github.com/users/eclipse/repos","events_url":"https://api.github.com/users/eclipse/events{/privacy}","received_events_url":"https://api.github.com/users/eclipse/received_events","type":"Organization","site_admin":false},"repo":{"id":43075480,"node_id":"MDEwOlJlcG9zaXRvcnk0MzA3NTQ4MA==","name":"californium","full_name":"eclipse/californium","owner":{"login":"eclipse","id":56974,"node_id":"MDEyOk9yZ2FuaXphdGlvbjU2OTc0","avatar_url":"https://avatars1.githubusercontent.com/u/56974?v=4","gravatar_id":"","url":"https://api.github.com/users/eclipse","html_url":"https://github.com/eclipse","followers_url":"https://api.github.com/users/eclipse/followers","following_url":"https://api.github.com/users/eclipse/following{/other_user}","gists_url":"https://api.github.com/users/eclipse/gists{/gist_id}","starred_url":"https://api.github.com/users/eclipse/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/eclipse/subscriptions","organizations_url":"https://api.github.com/users/eclipse/orgs","repos_url":"https://api.github.com/users/eclipse/repos","events_url":"https://api.github.com/users/eclipse/events{/privacy}","received_events_url":"https://api.github.com/users/eclipse/received_events","type":"Organization","site_admin":false},"private":false,"html_url":"https://github.com/eclipse/californium","description":null,"fork":false,"url":"https://api.github.com/repos/eclipse/californium","forks_url":"https://api.github.com/repos/eclipse/californium/forks","keys_url":"https://api.github.com/repos/eclipse/californium/keys{/key_id}","collaborators_url":"https://api.github.com/repos/eclipse/californium/collaborators{/collaborator}","teams_url":"https://api.github.com/repos/eclipse/californium/teams","hooks_url":"https://api.github.com/repos/eclipse/californium/hooks","issue_events_url":"https://api.github.com/repos/eclipse/californium/issues/events{/number}","events_url":"https://api.github.com/repos/eclipse/californium/events","assignees_url":"https://api.github.com/repos/eclipse/californium/assignees{/user}","branches_url":"https://api.github.com/repos/eclipse/californium/branches{/branch}","tags_url":"https://api.github.com/repos/eclipse/californium/tags","blobs_url":"https://api.github.com/repos/eclipse/californium/git/blobs{/sha}","git_tags_url":"https://api.github.com/repos/eclipse/californium/git/tags{/sha}","git_refs_url":"https://api.github.com/repos/eclipse/californium/git/refs{/sha}","trees_url":"https://api.github.com/repos/eclipse/californium/git/trees{/sha}","statuses_url":"https://api.github.com/repos/eclipse/californium/statuses/{sha}","languages_url":"https://api.github.com/repos/eclipse/californium/languages","stargazers_url":"https://api.github.com/repos/eclipse/californium/stargazers","contributors_url":"https://api.github.com/repos/eclipse/californium/contributors","subscribers_url":"https://api.github.com/repos/eclipse/californium/subscribers","subscription_url":"https://api.github.com/repos/eclipse/californium/subscription","commits_url":"https://api.github.com/repos/eclipse/californium/commits{/sha}","git_commits_url":"https://api.github.com/repos/eclipse/californium/git/commits{/sha}","comments_url":"https://api.github.com/repos/eclipse/californium/comments{/number}","issue_comment_url":"https://api.github.com/repos/eclipse/californium/issues/comments{/number}","contents_url":"https://api.github.com/repos/eclipse/californium/contents/{+path}","compare_url":"https://api.github.com/repos/eclipse/californium/compare/{base}...{head}","merges_url":"https://api.github.com/repos/eclipse/californium/merges","archive_url":"https://api.github.com/repos/eclipse/californium/{archive_format}{/ref}","downloads_url":"https://api.github.com/repos/eclipse/californium/downloads","issues_url":"https://api.github.com/repos/eclipse/californium/issues{/number}","pulls_url":"https://api.github.com/repos/eclipse/californium/pulls{/number}","milestones_url":"https://api.github.com/repos/eclipse/californium/milestones{/number}","notifications_url":"https://api.github.com/repos/eclipse/californium/notifications{?since,all,participating}","labels_url":"https://api.github.com/repos/eclipse/californium/labels{/name}","releases_url":"https://api.github.com/repos/eclipse/californium/releases{/id}","deployments_url":"https://api.github.com/repos/eclipse/californium/deployments","created_at":"2015-09-24T15:27:15Z","updated_at":"2018-06-11T03:07:49Z","pushed_at":"2018-06-09T06:48:10Z","git_url":"git://github.com/eclipse/californium.git","ssh_url":"git@github.com:eclipse/californium.git","clone_url":"https://github.com/eclipse/californium.git","svn_url":"https://github.com/eclipse/californium","homepage":null,"size":6982,"stargazers_count":224,"watchers_count":224,"language":"Java","has_issues":true,"has_projects":true,"has_downloads":true,"has_wiki":true,"has_pages":false,"forks_count":180,"mirror_url":null,"archived":false,"open_issues_count":31,"license":{"key":"other","name":"Other","spdx_id":null,"url":null,"node_id":"MDc6TGljZW5zZTA="},"forks":180,"open_issues":31,"watchers":224,"default_branch":"master"}},"_links":{"self":{"href":"https://api.github.com/repos/eclipse/californium/pulls/650"},"html":{"href":"https://github.com/eclipse/californium/pull/650"},"issue":{"href":"https://api.github.com/repos/eclipse/californium/issues/650"},"comments":{"href":"https://api.github.com/repos/eclipse/californium/issues/650/comments"},"review_comments":{"href":"https://api.github.com/repos/eclipse/californium/pulls/650/comments"},"review_comment":{"href":"https://api.github.com/repos/eclipse/californium/pulls/comments{/number}"},"commits":{"href":"https://api.github.com/repos/eclipse/californium/pulls/650/commits"},"statuses":{"href":"https://api.github.com/repos/eclipse/californium/statuses/36b04709d1878eebd88dfb4f8805cdc0ebcb7d15"}},"author_association":"NONE"}}
{"actor":{"display_login":"T0bbe"}}