public static CBORObject RandomCBORArray(RandomGenerator rand, int depth) { int x = rand.UniformInt(100); int count = (x < 80) ? 2 : ((x < 93) ? 1 : ((x < 98) ? 0 : 10)); CBORObject cborRet = CBORObject.NewArray(); for (var i = 0; i < count; ++i) { cborRet.Add(RandomCBORObject(rand, depth + 1)); } return(cborRet); }
private byte[] BuildContentBytes() #endif { CBORObject obj = CBORObject.NewArray(); obj.Add(strContext); if (objProtected.Count > 0) { obj.Add(objProtected.EncodeToBytes()); } else { obj.Add(CBORObject.FromObject(new byte[0])); } if (externalData != null) { obj.Add(CBORObject.FromObject(externalData)); } else { obj.Add(CBORObject.FromObject(new byte[0])); } obj.Add(rgbContent); return(obj.EncodeToBytes()); }
private static void SerializeAttribute(string name, List <string> values, CBORObject cbor, Dictionary <string, CBORObject> dictionary) { bool useSpace = SpaceSeparatedValueAttributes.Contains(name); CBORObject result; if (useSpace && values.Count > 1) { StringBuilder sb = new StringBuilder(); foreach (string value in values) { sb.Append(value); sb.Append(" "); } sb.Length = sb.Length - 1; result = CBORObject.FromObject(sb.ToString()); } else if (values.Count == 1) { string value = values.First(); if (string.IsNullOrEmpty(value)) { result = CBORObject.True; } else { result = CBORObject.FromObject(values.First()); } } else { result = CBORObject.NewArray(); foreach (string value in values) { if (string.IsNullOrEmpty(value)) { result.Add(CBORObject.True); } else { result.Add(value); } } } CBORObject pair = CBORObject.NewArray(); pair.Add(name); pair.Add(result); cbor.Add(pair); }
public byte[] getAADBytes() { CBORObject obj = CBORObject.NewArray(); obj.Add(_context); if (ProtectedMap.Count == 0) { ProtectedBytes = new byte[0]; } else { ProtectedBytes = ProtectedMap.EncodeToBytes(); } obj.Add(ProtectedBytes); obj.Add(CBORObject.FromObject(ExternalData)); // Console.WriteLine("COSE AAD = " + BitConverter.ToString(obj.EncodeToBytes())); return(obj.EncodeToBytes()); }
public void codeWrongCount() { CBORObject obj = CBORObject.NewArray(); obj.Add(CBORObject.False); byte[] rgb = obj.EncodeToBytes(); CoseException e = Assert.ThrowsException <CoseException>(() => Message.DecodeFromBytes(rgb, Tags.Sign1)); Assert.AreEqual(e.Message, ("Invalid Sign1 structure")); }
public void signerDecodeWrongCount() { CBORObject obj = CBORObject.NewArray(); obj.Add(CBORObject.False); Signer sig = new Signer(); CoseException e = Assert.ThrowsException <CoseException>(() => sig.DecodeFromCBORObject(obj)); Assert.AreEqual(e.Message, ("Invalid Signer structure")); }
public CBORObject EncodeToCBOR(CBORObject fieldArray, Cori baseCori, CoralDictionary dictionary) { fieldArray.Add(dictionary.Lookup(FieldType, false)); if (Literal != null) { fieldArray.Add(dictionary.Lookup(Literal, true)); } else { CBORObject x = dictionary.Lookup(Url, true); if (x.Type == CBORType.Integer) { fieldArray.Add(x); } else { fieldArray.Add(Url.MakeRelative(baseCori).Data); } } return(fieldArray); }
private byte[] toBeSigned() { CBORObject cborProtected = CBORObject.FromObject(new byte[0]); if ((ProtectedMap != null) && (ProtectedMap.Count > 0)) { byte[] rgb = ProtectedMap.EncodeToBytes(); cborProtected = CBORObject.FromObject(rgb); } CBORObject signObj = CBORObject.NewArray(); signObj.Add(_context); signObj.Add(cborProtected); signObj.Add(ExternalData); // External AAD signObj.Add(rgbContent); #if FOR_EXAMPLES m_toBeSigned = signObj.EncodeToBytes(); #endif return(signObj.EncodeToBytes()); }
private static void KdcJoin(string[] cmds) { if (cmds.Length != 3) { Console.WriteLine("Incorrect number of parameters"); return; } if ((Program._CurrentOscore == null) || (Program._CurrentOscore.UserData == null) || !(Program._CurrentOscore.UserData is GroupData)) { Console.WriteLine("Can't use the current OSCORE context"); return; } GroupData groupData = (GroupData)Program._CurrentOscore.UserData; OneKey signKey = OneKey.GenerateKey(null, GeneralValues.KeyType_OKP, "Ed25519"); byte[] signature = Signer.Sign(groupData.SignNonce, groupData.SignInfo[0], signKey); CBORObject join = CBORObject.NewMap(); CBORObject j2 = CBORObject.NewMap(); j2.Add(Confirmation.ConfirmationIds.COSE_Key, signKey.AsCBOR()); join.Add("type", 1); join.Add("client_cred", j2); join.Add("client_cred_verify", signature); Request request = new Request(Method.POST) { URI = new Uri(cmds[1]), Payload = @join.EncodeToBytes(), ContentType = MediaType.ApplicationCbor, OscoreContext = Program._CurrentOscore }; request.Send(); Response response = request.WaitForResponse(); if (response == null || response.StatusCode != StatusCode.Changed) { Console.WriteLine("Error in the response"); return; } CBORObject respBody = CBORObject.DecodeFromBytes(response.Payload); }
private byte[] toBeSigned(byte[] rgbContent, byte[] bodyAttributes) { CBORObject cborProtected = CBORObject.FromObject(new byte[0]); if ((objProtected != null) && (objProtected.Count > 0)) { byte[] rgb = objProtected.EncodeToBytes(); cborProtected = CBORObject.FromObject(rgb); } CBORObject signObj = CBORObject.NewArray(); signObj.Add(context); signObj.Add(bodyAttributes); signObj.Add(cborProtected); signObj.Add(externalData); signObj.Add(rgbContent); #if FOR_EXAMPLES m_toBeSigned = signObj.EncodeToBytes(); #endif return(signObj.EncodeToBytes()); }
public CBORObject EncodeToJSON(byte[] body) { CBORObject obj = CBORObject.NewMap(); if (protectedB64 != null) { obj.Add("protected", protectedB64); } else if (ProtectedMap.Count > 0) { protectedB64 = Message.base64urlencode(Encoding.UTF8.GetBytes(JSON.ToJsonString(ProtectedMap))); obj.Add("protected", protectedB64); } if (UnprotectedMap.Count > 0) { obj.Add("header", UnprotectedMap); // Add unprotected attributes } String str = ""; if (ProtectedMap.ContainsKey("b64") && ProtectedMap["b64"].AsBoolean() == false) { str += protectedB64 + "." + Encoding.UTF8.GetString(body); } else { str += protectedB64 + "." + Message.base64urlencode(body); } #if DEBUG ToBeSigned = str; #endif obj.Add("signature", Message.base64urlencode(Sign(Encoding.UTF8.GetBytes(str)))); return(obj); }
public byte[] CreateMessage3() { CBORObject msg = CBORObject.NewArray(); if (_fSymmetricSecret) { msg.Add(6); } else { msg.Add(3); } msg.Add(_SessionId[1]); byte[] aad_3 = ConcatenateAndHash(new byte[2][] { _LastMessageAuthenticator, msg.EncodeToBytes() }, _MessageDigest); byte[] signBody = new byte[0]; if (!_fSymmetricSecret) { Sign1Message sign1 = new Sign1Message(false, false); sign1.SetContent(aad_3); sign1.AddAttribute(HeaderKeys.Algorithm, _algSign, Attributes.DO_NOT_SEND); sign1.AddAttribute(HeaderKeys.KeyId, _SigningKey[CoseKeyKeys.KeyIdentifier], Attributes.UNPROTECTED); sign1.Sign(_SigningKey); CBORObject obj = CBORObject.NewArray(); obj.Add(sign1.EncodeToBytes()); signBody = obj.EncodeToBytes(); } byte[][] encKeys = _DeriveKeys(_Keys, _SecretSalt, aad_3, _algAEAD); Encrypt0Message enc = new Encrypt0Message(false); enc.SetContent(signBody); enc.SetExternalData(aad_3); enc.AddAttribute(HeaderKeys.Algorithm, _algAEAD, Attributes.DO_NOT_SEND); enc.AddAttribute(HeaderKeys.IV, CBORObject.FromObject(encKeys[1]), Attributes.DO_NOT_SEND); enc.Encrypt(encKeys[0]); msg.Add(enc.EncodeToBytes()); byte[] msgOut = msg.EncodeToBytes(); _LastMessageAuthenticator = ConcatenateAndHash(new byte[2][] { _LastMessageAuthenticator, msgOut }, _MessageDigest); return(msgOut); }
private static CBORObject readList(Stream stream) { CBORObject obj = CBORObject.NewArray(); while (true) { CBORObject o = readObject(stream, true); if (o == null) { break; // 'e' was read } obj.Add(o); } return(obj); }
public CBORObject EncodeToCBORObject(CoralDictionary dictionary = null) { CBORObject root = CBORObject.NewArray(); if (dictionary == null) { dictionary = CoralDictionary.Default; } foreach (CoralItem item in _items) { root.Add(item.EncodeToCBORObject(dictionary)); } return(root); }
/// <summary> /// Generate a new CBOR Object based on the message. /// Doing this will force cryptographic operations to be created. /// </summary> /// <returns></returns> public CBORObject EncodeToCBORObject() { CBORObject obj = CBORObject.NewArray(); CBORObject obj3 = Encode(); for (int i = 0; i < obj3.Count; i++) { obj.Add(obj3[i]); } if (m_emitTag) { return(CBORObject.FromObjectAndTag(obj, (int)m_tag)); } return(obj); }
private static void SerializeResource(IResource resource, CBORObject cbor, Dictionary <string, CBORObject> dictionary) { CBORObject obj = CBORObject.NewMap(); if (dictionary == null) { obj.Add("href", resource.Path + resource.Name); } else { obj.Add(1, resource.Path + resource.Name); } SerializeAttributes(resource.Attributes, obj, dictionary); cbor.Add(obj); }
public CBORObject EncodeToCBORObject(Cori coriBase, CoralDictionary dictionary = null) { CBORObject root = CBORObject.NewArray(); if (dictionary == null) { dictionary = CoralDictionary.Default; } foreach (CoralItem item in _items) { root.Add(item.EncodeToCBORObject(coriBase, dictionary)); if (item is CoralBaseDirective d) { coriBase = d.BaseValue.ResolveTo(coriBase); } } return(root); }
/// <summary>Fill byte array with random values.</summary> /// <param name="bytes">Array to receive bytes.</param> /// <param name="start">Index to start filling at.</param> /// <param name="len">Length of segment to fill.</param> public override void NextBytes(byte[] bytes, int start, int len) { if (m_iRngData + len > m_rgbRngData.Length) { if (m_prng == null) { m_prng = new SecureRandom(); } int cbOld = m_rgbRngData.Length; Array.Resize(ref m_rgbRngData, m_iRngData + len); m_prng.NextBytes(m_rgbRngData, cbOld, m_rgbRngData.Length - cbOld); m_fDirty = true; } Array.Copy(m_rgbRngData, m_iRngData, bytes, start, len); byte[] x = new byte[len]; Array.Copy(m_rgbRngData, m_iRngData, x, 0, len); objNew.Add(CBORObject.FromObject(Program.ToHex(x))); m_iRngData += len; }
public void SetClaim(string claim, CBORObject value) { switch (claim) { case "iss": case "sub": case "aud": if (value.Type != CBORType.TextString) { throw new JwtException("Claim value type is incorrect for the claim"); } break; case "exp": case "nbf": case "iat": if (value.Type != CBORType.Integer) { throw new JwtException("Claim value type is incorrect for the claim"); } break; case "jti": if (value.Type != CBORType.TextString) { throw new JwtException("Claim value type is incorrect for the claim"); } break; default: // We don't know how to check this break; } _claims.Add(claim, value); }
protected void ProcessCounterSignatures() { if (CounterSignerList.Count != 0) { if (CounterSignerList.Count == 1) { AddAttribute(HeaderKeys.CounterSignature, CounterSignerList[0].EncodeToCBORObject(ProtectedBytes, rgbSignature), UNPROTECTED); } else { CBORObject list = CBORObject.NewArray(); foreach (CounterSignature sig in CounterSignerList) { list.Add(sig.EncodeToCBORObject(ProtectedBytes, rgbSignature)); } AddAttribute(HeaderKeys.CounterSignature, list, UNPROTECTED); } } if (CounterSigner1 != null) { AddAttribute(HeaderKeys.CounterSignature0, CounterSigner1.EncodeToCBORObject(ProtectedBytes, rgbSignature), UNPROTECTED); } }
/// <inheritdoc /> public override void ReceiveRequest(INextLayer nextLayer, Exchange exchange, Request request) { if (!request.HasOption(OptionType.Oscoap)) { base.ReceiveRequest(nextLayer, exchange, request); return; } Response response; try { Option op = request.GetFirstOption(OptionType.Oscoap); request.RemoveOptions(OptionType.Oscoap); _Log.Info(m => m("Incoming Request: {0}", Util.Utils.ToString(request))); Encrypt0Message msg = Uncompress(op.RawValue); if (msg == null) { // Only bother to reply to CON messages if (request.Type == MessageType.CON) { response = new Response(StatusCode.BadOption) { PayloadString = "Unable to decompress" }; exchange.SendResponse(response); } return; } msg.SetEncryptedContent(request.Payload); List <SecurityContext> contexts = new List <SecurityContext>(); SecurityContext ctx = null; CBORObject kid; // We may know the context because it is a follow up on a conversation - // In which case we can just use the same one. // M00BUG - Multicast problem of recipient ID? CBORObject gid = null; if (exchange.OscoapContext != null) { contexts.Add(exchange.OscoapContext); if (exchange.OscoapContext.GroupId != null) { gid = CBORObject.FromObject(exchange.OscoapContext.GroupId); } kid = CBORObject.FromObject(exchange.OscoapSenderId); } else { gid = msg.FindAttribute(CBORObject.FromObject("gid")); kid = msg.FindAttribute(HeaderKeys.KeyId); if (kid == null) { exchange.SendResponse(new Response(StatusCode.BadRequest)); return; } if (gid != null) { contexts = SecurityContextSet.AllContexts.FindByGroupId(gid.GetByteString()); } else { contexts = SecurityContextSet.AllContexts.FindByKid(kid.GetByteString()); } if (contexts.Count == 0) { response = new Response(StatusCode.Unauthorized) { PayloadString = "No Context Found - 1" }; exchange.SendResponse(response); return; // Ignore messages that have no known security context. } } byte[] partialIV = msg.FindAttribute(HeaderKeys.PartialIV).GetByteString(); // Build AAD CBORObject aad = CBORObject.NewArray(); aad.Add(CBORObject.FromObject(1)); // M00BUG aad.Add(CBORObject.NewArray()); // Array place holder aad[1].Add(CBORObject.FromObject(0)); // Place holder for algorithm aad.Add(CBORObject.FromObject(kid)); aad.Add(CBORObject.FromObject(partialIV)); aad.Add(CBORObject.FromObject(new byte[0])); // encoded I options if (gid != null) { aad.Add(gid); } byte[] payload = null; byte[] seqNoArray = new byte[8]; Array.Copy(partialIV, 0, seqNoArray, 8 - partialIV.Length, partialIV.Length); if (BitConverter.IsLittleEndian) { Array.Reverse(seqNoArray); } Int64 seqNo = BitConverter.ToInt64(seqNoArray, 0); String responseString = "General decrypt failure"; foreach (SecurityContext context in contexts) { SecurityContext.EntityContext recip = context.Recipient; if (recip == null) { if (kid == null) { continue; } recip = context.Recipients[kid.GetByteString()]; if (recip == null) { continue; } } if (_replayWindow && recip.ReplayWindow.HitTest(seqNo)) { _Log.Info(m => m("Hit test on {0} failed", seqNo)); responseString = "Hit test - duplicate"; continue; } aad[1][0] = recip.Algorithm; if (_Log.IsInfoEnabled) { _Log.Info("AAD = " + BitConverter.ToString(aad.EncodeToBytes())); _Log.Info("IV = " + BitConverter.ToString(recip.GetIV(partialIV).GetByteString())); _Log.Info("Key = " + BitConverter.ToString(recip.Key)); } msg.SetExternalData(aad.EncodeToBytes()); msg.AddAttribute(HeaderKeys.Algorithm, recip.Algorithm, Attributes.DO_NOT_SEND); msg.AddAttribute(HeaderKeys.IV, recip.GetIV(partialIV), Attributes.DO_NOT_SEND); try { ctx = context; payload = msg.Decrypt(recip.Key); recip.ReplayWindow.SetHit(seqNo); } catch (Exception e) { if (_Log.IsInfoEnabled) { _Log.Info("--- ", e); } ctx = null; } if (ctx != null) { break; } } if (ctx == null) { if (request.Type == MessageType.CON) { response = new Response(StatusCode.BadRequest) { PayloadString = responseString }; exchange.SendResponse(response); } return; } exchange.OscoapContext = ctx; // So we know it on the way back. request.OscoapContext = ctx; exchange.OscoapSequenceNumber = partialIV; exchange.OscoapSenderId = kid.GetByteString(); byte[] newRequestData = new byte[payload.Length + _FixedHeader.Length - 1]; Array.Copy(_FixedHeader, newRequestData, _FixedHeader.Length); Array.Copy(payload, 1, newRequestData, _FixedHeader.Length, payload.Length - 1); newRequestData[1] = payload[0]; Codec.IMessageDecoder me = Spec.NewMessageDecoder(newRequestData); Request newRequest = me.DecodeRequest(); // Update headers is a pain RestoreOptions(request, newRequest); request.Method = newRequest.Method; if (_Log.IsInfoEnabled) { // log.Info(String.Format("Secure message post = " + Util.Utils.ToString(request))); } // We may want a new exchange at this point if it relates to a new message for blockwise. if (request.HasOption(OptionType.Block2)) { Exchange.KeyUri keyUri = new Exchange.KeyUri(request.URI, null, request.Source); BlockHolder block; _ongoingExchanges.TryGetValue(keyUri, out block); if (block != null) { block.RestoreTo(exchange); } } request.Payload = newRequest.Payload; } catch (Exception e) { _Log.Error("OSCOAP Layer: reject message because ", e); exchange.OscoapContext = null; if (request.Type == MessageType.CON) { response = new Response(StatusCode.Unauthorized) { Payload = Encoding.UTF8.GetBytes("Error is " + e.Message) }; exchange.SendResponse(response); } // Ignore messages that we cannot decrypt. return; } base.ReceiveRequest(nextLayer, exchange, request); }
#pragma warning restore 618 private static void FromArrayRecursive( Array arr, int[] index, int dimension, CBORObject obj) { int dimLength = arr.GetLength(dimension); int rank = index.Length; for (var i = 0; i < dimLength; ++i) { if (dimension + 1 == rank) { index[dimension] = i; obj.Add(CBORObject.FromObject(arr.GetValue(index))); } else { CBORObject child = CBORObject.NewArray(); for (int j = dimension + 1; j < dimLength; ++j) { index[j] = 0; } FromArrayRecursive(arr, index, dimension + 1, child); obj.Add(child); } } }
/// <inheritdoc /> protected override CBORObject InternalEncodeToJSON(bool fCompact) { CBORObject obj = CBORObject.NewMap(); if (UnprotectedMap.Count > 0) { obj.Add("unprotected", UnprotectedMap); // Add unprotected attributes } // Look at the world of base64 encoded bodies. // If any signer has the b64 false, then all of them need to. // Then change our body if needed int b64Found = 0; bool b64Value = true; foreach (Signer key in SignerList) { CBORObject attr = key.FindAttribute(CBORObject.FromObject("b64"), PROTECTED); if (attr != null) { if (b64Found == 0) { b64Value = attr.AsBoolean(); } else if (b64Value != attr.AsBoolean()) { throw new JoseException("Not all signers using the same value for b64"); } b64Found += 1; } } if (b64Value) { obj.Add("payload", base64urlencode(payload)); } else { if (b64Found != SignerList.Count) { throw new JoseException("Not all signers using the same value for b64"); } obj.Add("payload", Encoding.UTF8.GetString(payload)); } if (SignerList.Count > 0) { CBORObject signers = CBORObject.NewArray(); foreach (Signer key in SignerList) { signers.Add(key.EncodeToJSON(payload)); } if (fCompact) { if (SignerList.Count > 1) { throw new JoseException("Compact format must be for single signer"); } if (signers[0].ContainsKey("protected")) { obj.Add("protected", signers[0]["protected"]); } obj.Add("signature", signers[0]["signature"]); } else { obj.Add("signatures", signers); } } else { throw new JoseException("Must have some signers"); } return(obj); }
public void Add(string key, string value) { _json.Add(key, CBORObject.FromObject(value)); }
/// <summary> /// Given the set of inputs, perform the crptographic operations that are needed /// to build a security context for a single sender and recipient. /// </summary> /// <param name="masterSecret">pre-shared key</param> /// <param name="senderId">name assigned to sender</param> /// <param name="recipientId">name assigned to recipient</param> /// <param name="masterSalt">salt value</param> /// <param name="algAEAD">encryption algorithm</param> /// <param name="algKeyAgree">key agreement algorithm</param> /// <returns></returns> public static SecurityContext DeriveContext(byte[] masterSecret, byte[] senderId, byte[] recipientId, byte[] masterSalt = null, CBORObject algAEAD = null, CBORObject algKeyAgree = null) { SecurityContext ctx = new SecurityContext(); if (algAEAD == null) { ctx.Sender.Algorithm = AlgorithmValues.AES_CCM_64_64_128; } else { ctx.Sender.Algorithm = algAEAD; } ctx.Sender.Id = senderId ?? throw new ArgumentNullException(nameof(senderId)); ctx.Recipient = new EntityContext { Algorithm = ctx.Sender.Algorithm, Id = recipientId ?? throw new ArgumentNullException(nameof(recipientId)), ReplayWindow = new ReplayWindow(0, 64) }; CBORObject info = CBORObject.NewArray(); info.Add(senderId); // 0 info.Add(ctx.Sender.Algorithm); // 1 info.Add("Key"); // 2 info.Add(128 / 8); // 3 in bytes IDigest sha256; if (algKeyAgree == null || algKeyAgree.Equals(AlgorithmValues.ECDH_SS_HKDF_256)) { sha256 = new Sha256Digest(); } else if (algKeyAgree.Equals(AlgorithmValues.ECDH_SS_HKDF_512)) { sha256 = new Sha512Digest(); } else { throw new ArgumentException("Unrecognized key agreement algorithm"); } IDerivationFunction hkdf = new HkdfBytesGenerator(sha256); hkdf.Init(new HkdfParameters(masterSecret, masterSalt, info.EncodeToBytes())); ctx.Sender.Key = new byte[128 / 8]; hkdf.GenerateBytes(ctx.Sender.Key, 0, ctx.Sender.Key.Length); info[0] = CBORObject.FromObject(recipientId); hkdf.Init(new HkdfParameters(masterSecret, masterSalt, info.EncodeToBytes())); ctx.Recipient.Key = new byte[128 / 8]; hkdf.GenerateBytes(ctx.Recipient.Key, 0, ctx.Recipient.Key.Length); info[2] = CBORObject.FromObject("IV"); info[3] = CBORObject.FromObject(56 / 8); hkdf.Init(new HkdfParameters(masterSecret, masterSalt, info.EncodeToBytes())); ctx.Recipient.BaseIV = new byte[56 / 8]; hkdf.GenerateBytes(ctx.Recipient.BaseIV, 0, ctx.Recipient.BaseIV.Length); info[0] = CBORObject.FromObject(senderId); hkdf.Init(new HkdfParameters(masterSecret, masterSalt, info.EncodeToBytes())); ctx.Sender.BaseIV = new byte[56 / 8]; hkdf.GenerateBytes(ctx.Sender.BaseIV, 0, ctx.Sender.BaseIV.Length); // Give a unique context number for doing comparisons ctx.ContextNo = _ContextNumber; _ContextNumber += 1; return(ctx); }
/// <inheritdoc /> public override void SendRequest(INextLayer nextLayer, Exchange exchange, Request request) { if ((request.OscoapContext != null) || (exchange.OscoapContext != null)) { SecurityContext ctx = exchange.OscoapContext; if (request.OscoapContext != null) { ctx = request.OscoapContext; exchange.OscoapContext = ctx; } Codec.IMessageEncoder me = Spec.NewMessageEncoder(); Request encryptedRequest = new Request(request.Method); if (request.Payload != null) { encryptedRequest.Payload = request.Payload; } MoveRequestHeaders(request, encryptedRequest); _Log.Info(m => m("New inner response message\n{0}", encryptedRequest.ToString())); ctx.Sender.IncrementSequenceNumber(); Encrypt0Message enc = new Encrypt0Message(false); byte[] msg = me.Encode(encryptedRequest); int tokenSize = msg[0] & 0xf; byte[] msg2 = new byte[msg.Length - (3 + tokenSize)]; Array.Copy(msg, 4 + tokenSize, msg2, 1, msg2.Length - 1); msg2[0] = msg[1]; enc.SetContent(msg2); // Build AAD CBORObject aad = CBORObject.NewArray(); aad.Add(CBORObject.FromObject(1)); // version aad.Add(CBORObject.NewArray()); aad[1].Add(CBORObject.FromObject(ctx.Sender.Algorithm)); aad.Add(CBORObject.FromObject(ctx.Sender.Id)); aad.Add(CBORObject.FromObject(ctx.Sender.PartialIV)); aad.Add(CBORObject.FromObject(new byte[0])); if (ctx.GroupId != null) { aad.Add(CBORObject.FromObject(ctx.GroupId)); } #if DEBUG switch (SecurityContext.FutzError) { case 1: aad[0] = CBORObject.FromObject(2); break; // Change version # case 2: aad[1] = CBORObject.FromObject(request.Code + 1); break; // Change request code case 3: aad[2] = CBORObject.FromObject(ctx.Sender.Algorithm.AsInt32() + 1); break; // Change algorithm number } #endif _Log.Info(m => m("SendRequest: AAD = {0}", BitConverter.ToString(aad.EncodeToBytes()))); enc.SetExternalData(aad.EncodeToBytes()); #if DEBUG { byte[] fooX = ctx.Sender.PartialIV; if (SecurityContext.FutzError == 8) { fooX[fooX.Length - 1] += 1; } enc.AddAttribute(HeaderKeys.IV, ctx.Sender.GetIV(fooX), Attributes.DO_NOT_SEND); } #else enc.AddAttribute(HeaderKeys.IV, ctx.Sender.GetIV(ctx.Sender.PartialIV), Attributes.DO_NOT_SEND); #endif enc.AddAttribute(HeaderKeys.PartialIV, CBORObject.FromObject(ctx.Sender.PartialIV), /* Attributes.PROTECTED */ Attributes.DO_NOT_SEND); enc.AddAttribute(HeaderKeys.Algorithm, ctx.Sender.Algorithm, Attributes.DO_NOT_SEND); enc.AddAttribute(HeaderKeys.KeyId, CBORObject.FromObject(ctx.Sender.Id), /*Attributes.PROTECTED*/ Attributes.DO_NOT_SEND); if (ctx.GroupId != null) { enc.AddAttribute(CBORObject.FromObject("gid"), CBORObject.FromObject(ctx.GroupId), Attributes.DO_NOT_SEND); } if (_Log.IsInfoEnabled) { _Log.Info("SendRequest: AAD = " + BitConverter.ToString(aad.EncodeToBytes())); _Log.Info("SendRequest: IV = " + BitConverter.ToString(ctx.Sender.GetIV(ctx.Sender.PartialIV).GetByteString())); _Log.Info("SendRequest: Key = " + BitConverter.ToString(ctx.Sender.Key)); } enc.Encrypt(ctx.Sender.Key); if (ctx.Sender.SigningKey != null) { CounterSignature sig = new CounterSignature(ctx.Sender.SigningKey); sig.AddAttribute(HeaderKeys.Algorithm, ctx.Sender.SigningKey[CoseKeyKeys.Algorithm], Attributes.DO_NOT_SEND); sig.SetObject(enc); CBORObject aad2 = ctx.Sender.SigningKey[CoseKeyKeys.Algorithm]; sig.SetExternalData(aad2.EncodeToBytes()); CBORObject signatureBytes = sig.EncodeToCBORObject(); enc.AddAttribute(HeaderKeys.CounterSignature, signatureBytes, Attributes.DO_NOT_SEND); } byte[] optionValue = DoCompression(enc); OscoapOption o = new OscoapOption(); o.Set(optionValue); request.AddOption(o); request.Payload = enc.GetEncryptedContent(); if (request.HasOption(OptionType.Observe)) { request.Method = Method.FETCH; } else { request.Method = Method.POST; } } base.SendRequest(nextLayer, exchange, request); }
public override void SendResponse(INextLayer nextLayer, Exchange exchange, Response response) { if (exchange.OscoapContext != null) { SecurityContext ctx = exchange.OscoapContext; Codec.IMessageEncoder me = Spec.NewMessageEncoder(); Response encryptedResponse = new Response((StatusCode)response.Code); if (response.Payload != null) { encryptedResponse.Payload = response.Payload; } MoveResponseHeaders(response, encryptedResponse); if (_Log.IsInfoEnabled) { _Log.Info("SendResponse: New inner response message"); _Log.Info(encryptedResponse.ToString()); } // Build AAD CBORObject aad = CBORObject.NewArray(); aad.Add(1); aad.Add(CBORObject.NewArray()); aad[1].Add(ctx.Sender.Algorithm); aad.Add(exchange.OscoapSenderId); aad.Add(exchange.OscoapSequenceNumber); aad.Add(CBORObject.FromObject(new byte[0])); // Options if (ctx.GroupId != null) { aad.Add(ctx.GroupId); } if (_Log.IsInfoEnabled) { _Log.Info("SendResponse: AAD = " + BitConverter.ToString(aad.EncodeToBytes())); } Encrypt0Message enc = new Encrypt0Message(false); byte[] msg = me.Encode(encryptedResponse); int tokenSize = msg[0] & 0xf; byte[] msg2 = new byte[msg.Length - (3 + tokenSize)]; Array.Copy(msg, 4 + tokenSize, msg2, 1, msg2.Length - 1); msg2[0] = msg[1]; enc.SetContent(msg2); enc.SetExternalData(aad.EncodeToBytes()); if (response.HasOption(OptionType.Observe) || ctx.GroupId != null) { enc.AddAttribute(HeaderKeys.PartialIV, CBORObject.FromObject(ctx.Sender.PartialIV), Attributes.UNPROTECTED); enc.AddAttribute(HeaderKeys.IV, ctx.Sender.GetIV(ctx.Sender.PartialIV), Attributes.DO_NOT_SEND); ctx.Sender.IncrementSequenceNumber(); if (ctx.GroupId != null) { enc.AddAttribute(HeaderKeys.KeyId, CBORObject.FromObject(ctx.Sender.Id), Attributes.UNPROTECTED); } } else { CBORObject iv = ctx.Recipient.GetIV(exchange.OscoapSequenceNumber); enc.AddAttribute(HeaderKeys.IV, iv, Attributes.DO_NOT_SEND); } _Log.Info(m => m($"SendResponse: IV = {BitConverter.ToString(enc.FindAttribute(HeaderKeys.IV, Attributes.DO_NOT_SEND).GetByteString())}")); _Log.Info(m => m($"SendResponse: Key = {BitConverter.ToString(ctx.Sender.Key)}")); enc.AddAttribute(HeaderKeys.Algorithm, ctx.Sender.Algorithm, Attributes.DO_NOT_SEND); enc.Encrypt(ctx.Sender.Key); byte[] finalBody = DoCompression(enc); OscoapOption o = new OscoapOption(OptionType.Oscoap); o.Set(finalBody); response.AddOption(o); response.StatusCode = StatusCode.Content; response.Payload = enc.GetEncryptedContent(); // Need to be able to retrieve this again undersome cirumstances. if (encryptedResponse.HasOption(OptionType.Block2)) { Request request = exchange.CurrentRequest; Exchange.KeyUri keyUri = new Exchange.KeyUri(request.URI, null, response.Destination); // Observe notification only send the first block, hence do not store them as ongoing if (exchange.OSCOAP_ResponseBlockStatus != null && !encryptedResponse.HasOption(OptionType.Observe)) { // Remember ongoing blockwise GET requests BlockHolder blockInfo = new BlockHolder(exchange); if (Util.Utils.Put(_ongoingExchanges, keyUri, blockInfo) == null) { if (_Log.IsInfoEnabled) { _Log.Info("Ongoing Block2 started late, storing " + keyUri + " for " + request); } } else { if (_Log.IsInfoEnabled) { _Log.Info("Ongoing Block2 continued, storing " + keyUri + " for " + request); } } } else { if (_Log.IsInfoEnabled) { _Log.Info("Ongoing Block2 completed, cleaning up " + keyUri + " for " + request); } BlockHolder exc; _ongoingExchanges.TryRemove(keyUri, out exc); } } } base.SendResponse(nextLayer, exchange, response); }
public override void ReceiveResponse(INextLayer nextLayer, Exchange exchange, Response response) { if (response.HasOption(OptionType.Oscoap)) { Option op = response.GetFirstOption(OptionType.Oscoap); if (exchange.OscoapContext == null) { return; } SecurityContext ctx = exchange.OscoapContext; bool fServerIv = true; Encrypt0Message msg = Uncompress(op.RawValue); if (msg == null) { return; } msg.SetEncryptedContent(response.Payload); SecurityContext.EntityContext recip = ctx.Recipient; if (recip == null) { if (ctx.GroupId == null) { // This is not currently a valid state to be in return; } CBORObject kid = msg.FindAttribute(HeaderKeys.KeyId); if (kid == null) { // this is not currently a valid state to be in return; } recip = ctx.Recipients[kid.GetByteString()]; if (recip == null) { // M00TODO - deal with asking the user for a recipient structure at this point. return; } } if (msg.FindAttribute(HeaderKeys.PartialIV) == null) { msg.AddAttribute(HeaderKeys.PartialIV, CBORObject.FromObject(ctx.Sender.PartialIV), Attributes.DO_NOT_SEND); fServerIv = false; } byte[] partialIV = msg.FindAttribute(HeaderKeys.PartialIV).GetByteString(); byte[] seqNoArray = new byte[8]; Array.Copy(partialIV, 0, seqNoArray, 8 - partialIV.Length, partialIV.Length); if (BitConverter.IsLittleEndian) { Array.Reverse(seqNoArray); } Int64 seqNo = BitConverter.ToInt64(seqNoArray, 0); if (fServerIv) { if (_replayWindow && recip.ReplayWindow.HitTest(seqNo)) { return; } } msg.AddAttribute(HeaderKeys.Algorithm, recip.Algorithm, Attributes.DO_NOT_SEND); CBORObject fullIV; if (fServerIv) { fullIV = recip.GetIV(partialIV); } else { fullIV = ctx.Sender.GetIV(partialIV); } msg.AddAttribute(HeaderKeys.IV, fullIV, Attributes.DO_NOT_SEND); // build aad CBORObject aad = CBORObject.NewArray(); aad.Add(1); aad.Add(CBORObject.NewArray()); aad[1].Add(recip.Algorithm); aad.Add(ctx.Sender.Id); aad.Add(ctx.Sender.PartialIV); aad.Add(CBORObject.FromObject(new byte[0])); // OPTIONS if (ctx.GroupId != null) { aad.Add(ctx.GroupId); } msg.SetExternalData(aad.EncodeToBytes()); _Log.Info(m => m($"fServerIv = {fServerIv}")); _Log.Info(m => m("ReceiveResponse: AAD = " + BitConverter.ToString(aad.EncodeToBytes()))); _Log.Info(m => m($"ReceiveResponse: IV = {BitConverter.ToString(fullIV.GetByteString())}")); _Log.Info(m => m($"ReceiveResponse: Key = {BitConverter.ToString(recip.Key)}")); byte[] payload = msg.Decrypt(recip.Key); recip.ReplayWindow.SetHit(seqNo); byte[] rgb = new byte[payload.Length + _FixedHeader.Length - 1]; Array.Copy(_FixedHeader, rgb, _FixedHeader.Length); Array.Copy(payload, 1, rgb, _FixedHeader.Length, payload.Length - 1); rgb[1] = payload[0]; Codec.IMessageDecoder me = Spec.NewMessageDecoder(rgb); Response decryptedReq = me.DecodeResponse(); response.Payload = decryptedReq.Payload; response.StatusCode = decryptedReq.StatusCode; RestoreOptions(response, decryptedReq); } base.ReceiveResponse(nextLayer, exchange, response); }
public override CBORObject Encode() { CBORObject obj; byte[] rgbProtected; obj = CBORObject.NewArray(); if ((objProtected != null) && (objProtected.Count > 0)) { rgbProtected = objProtected.EncodeToBytes(); obj.Add(rgbProtected); } else { rgbProtected = new byte[0]; obj.Add(rgbProtected); } if (m_counterSignerList.Count() != 0) { if (m_counterSignerList.Count() == 1) { AddUnprotected(HeaderKeys.CounterSignature, m_counterSignerList[0].EncodeToCBORObject(rgbProtected, rgbContent)); } else { foreach (CounterSignature sig in m_counterSignerList) { sig.EncodeToCBORObject(rgbProtected, rgbContent); } } } if ((objUnprotected == null) || (objUnprotected.Count == 0)) { obj.Add(CBORObject.NewMap()); } else { obj.Add(objUnprotected); // Add unprotected attributes } obj.Add(rgbContent); if ((signerList.Count == 1) && !this.m_forceArray) { CBORObject recipient = signerList[0].EncodeToCBORObject(obj[0].EncodeToBytes(), rgbContent); for (int i = 0; i < recipient.Count; i++) { obj.Add(recipient[i]); } } else if (signerList.Count > 0) { CBORObject signers = CBORObject.NewArray(); foreach (Signer key in signerList) { signers.Add(key.EncodeToCBORObject(rgbProtected, rgbContent)); } obj.Add(signers); } else { obj.Add(null); // No recipients - set to null } return(obj); }
private static Encrypt0Message Uncompress(byte[] raw) { CBORObject map = CBORObject.NewMap(); if (raw.Length == 0) { raw = new byte[1]; } // Decode the wierd body // First byte is of the form 0abcdeee where abcd are flags and eee is the the IV size. if (0 != (raw[0] & 0x80)) { return(null); // This is not legal } if (0 != (raw[0] & 0x40)) { return(null); // These are not currently supported. } int iX = 1; if (0 != (raw[0] & 0x07)) { byte[] ivX = new byte[raw[0] & 0x7]; Array.Copy(raw, iX, ivX, 0, ivX.Length); map.Add(HeaderKeys.PartialIV, ivX); iX += ivX.Length; } if (0 != (raw[0] & 0x10)) { byte[] gidX = new byte[raw[iX]]; Array.Copy(raw, iX + 1, gidX, 0, gidX.Length); iX += (gidX.Length + 1); map.Add(CBORObject.FromObject("gid"), gidX); } if (0 != (raw[0] & 0x20)) { byte[] counter = new byte[raw[iX]]; Array.Copy(raw, iX + 1, counter, 0, counter.Length); iX += (counter.Length + 1); map.Add(HeaderKeys.CounterSignature, counter); } if (0 != (raw[0] & 0x08)) { byte[] kidX = new byte[raw.Length - iX]; Array.Copy(raw, iX, kidX, 0, kidX.Length); map.Add(HeaderKeys.KeyId, kidX); } CBORObject msgX = CBORObject.NewArray(); msgX.Add(new byte[0]); msgX.Add(map); msgX.Add(CBORObject.Null); Encrypt0Message msg = (Encrypt0Message)COSE.Message.DecodeFromBytes(msgX.EncodeToBytes(), Tags.Encrypt0); return(msg); }
public byte[] CreateMessage2() { CBORObject msg = CBORObject.NewArray(); CBORObject obj; if (_fSymmetricSecret) { msg.Add(5); // Msg Type } else { msg.Add(2); } msg.Add(_SessionId[1]); // S_U msg.Add(_SessionId[0]); // S_V msg.Add(_Nonce[0]); // N_V msg.Add(_Keys[0].PublicKey().AsCBOR()); // E_V msg.Add(_algKeyAgree); // HKDF_V msg.Add(_algAEAD); // AEAD_V if (!_fSymmetricSecret) { msg.Add(_algSign); // SIG_V obj = CBORObject.NewArray(); obj.Add(AlgorithmValuesInt.ECDSA_256); obj.Add(AlgorithmValues.EdDSA); msg.Add(obj); // SIGs_V } if (_algKeyAgree.Equals(COSE.AlgorithmValues.ECDH_SS_HKDF_256)) { _MessageDigest = new Sha256Digest(); } byte[] data2 = msg.EncodeToBytes(); byte[] aad_2 = ConcatenateAndHash(new byte[2][] { _Messages[0], data2 }, _MessageDigest); // M00TODO - hash message[0] before passing it in. byte[][] useKeys = _DeriveKeys(_Keys, _SecretSalt, aad_2, _algAEAD); byte[] aeadKey = useKeys[0]; byte[] signResult = new byte[0]; if (!_fSymmetricSecret) { Sign1Message sign1 = new Sign1Message(false, false); sign1.SetContent(aad_2); sign1.AddAttribute(HeaderKeys.KeyId, _SigningKey[CoseKeyKeys.KeyIdentifier], Attributes.UNPROTECTED); sign1.AddAttribute(HeaderKeys.Algorithm, _algSign, Attributes.DO_NOT_SEND); sign1.Sign(_SigningKey); signResult = sign1.EncodeToBytes(); } Encrypt0Message enc0 = new Encrypt0Message(true); enc0.AddAttribute(HeaderKeys.Algorithm, _algAEAD, Attributes.DO_NOT_SEND); enc0.AddAttribute(HeaderKeys.IV, CBORObject.FromObject(useKeys[1]), Attributes.DO_NOT_SEND); enc0.SetExternalData(aad_2); CBORObject encContent = CBORObject.NewArray(); encContent.Add(signResult); enc0.SetContent(encContent.EncodeToBytes()); enc0.Encrypt(aeadKey); msg.Add(enc0.EncodeToCBORObject()); // COSE_ENC_2 _Messages[1] = msg.EncodeToBytes(); _LastMessageAuthenticator = ConcatenateAndHash(new byte[][] { _Messages[0], _Messages[1] }, _MessageDigest); return(_Messages[1]); }