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); }
/// <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); }
/// <inheritdoc /> public override void SendRequest(INextLayer nextLayer, Exchange exchange, Request request) { if ((request.OscoreContext != null) || (exchange.OscoreContext != null)) { SecurityContext ctx = exchange.OscoreContext; if (request.OscoreContext != null) { ctx = request.OscoreContext; exchange.OscoreContext = 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()); // Algorithms aad[1].Add(CBORObject.FromObject(ctx.Sender.Algorithm)); if (ctx.Sender.SigningAlgorithm != null) { aad[1].Add(ctx.Sender.SigningAlgorithm); if (ctx.CountersignParams != null) { aad[1].Add(ctx.CountersignParams); } if (ctx.CountersignKeyParams != null) { aad[1].Add(ctx.CountersignKeyParams); } } aad.Add(CBORObject.FromObject(ctx.Sender.Id)); aad.Add(CBORObject.FromObject(ctx.Sender.PartialIV)); aad.Add(CBORObject.FromObject(new byte[0])); // I options go here _Log.Info(m => m("SendRequest: AAD = {0}", BitConverter.ToString(aad.EncodeToBytes()))); enc.SetExternalData(aad.EncodeToBytes()); enc.AddAttribute(HeaderKeys.IV, ctx.Sender.GetIV(ctx.Sender.PartialIV), Attributes.DO_NOT_SEND); 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(HeaderKeys.KidContext, CBORObject.FromObject(ctx.GroupId), Attributes.DO_NOT_SEND); } _Log.Info(m => m("SendRequest: AAD = {0}\nSendRequest: IV = {1}\nSendRequest: Key = {2}", BitConverter.ToString(aad.EncodeToBytes()), ctx.Sender.GetIV(ctx.Sender.PartialIV).GetByteString(), BitConverter.ToString(ctx.Sender.Key))); byte[] optionValue = BuildOscoreOption(enc); CounterSignature1 cs1 = null; if (ctx.Sender.SigningKey != null) { cs1 = new CounterSignature1(ctx.Sender.SigningKey); cs1.AddAttribute(HeaderKeys.Algorithm, ctx.Sender.SigningAlgorithm, Attributes.DO_NOT_SEND); aad.Add(optionValue); _Log.Info(m => m("SendRequest: AAD for Signature = {0}", BitConverter.ToString(aad.EncodeToBytes()))); cs1.SetExternalData(aad.EncodeToBytes()); cs1.SetObject(enc); enc.CounterSigner1 = cs1; } enc.Encrypt(ctx.Sender.Key); OscoapOption o = new OscoapOption(); o.Set(optionValue); request.AddOption(o); request.Payload = enc.GetEncryptedContent(); if (cs1 != null) { int cbOrig = request.Payload.Length; byte[] rgbOrig = request.Payload; byte[] signatureBytes = cs1.EncodeToCBORObject().GetByteString(); Array.Resize(ref rgbOrig, cbOrig + signatureBytes.Length); Array.Copy(signatureBytes, 0, rgbOrig, cbOrig, signatureBytes.Length); request.Payload = rgbOrig; } request.Method = request.HasOption(OptionType.Observe) ? Method.FETCH : Method.POST; request.Code = (int)request.Method; } base.SendRequest(nextLayer, exchange, request); }