예제 #1
0
        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);
        }
예제 #2
0
        public override void ReceiveResponse(INextLayer nextLayer, Exchange exchange, Response response)
        {
            if (response.HasOption(OptionType.Oscoap))
            {
                Option op = response.GetFirstOption(OptionType.Oscoap);

                if (exchange.OscoreContext == null)
                {
                    return;
                }

                _Log.Info($"Incoming message for OSCORE\n{Utils.ToString(response)}");

                SecurityContext ctx = exchange.OscoreContext;

                bool fServerIv = true;

                Encrypt0Message msg = Uncompress(op.RawValue);
                if (msg == null)
                {
                    return;
                }
                msg.SetEncryptedContent(response.Payload);

                SecurityContext.EntityContext recip = ctx.Recipient;
                if (ctx.IsGroupContext)
                {
                    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;
                    }
                }
                else
                {
                    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); // Version #
                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.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);
                    }
                }

                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)}"));

                if (ctx.IsGroupContext)
                {
                    aad.Add(op.RawValue);

                    int    cbSignature  = 64; // M00TODO   Need to figure out the size of the signature from the context.
                    byte[] rgbSignature = new byte[cbSignature];
                    byte[] rgbPayload   = new byte[response.Payload.Length - cbSignature];

                    Array.Copy(response.Payload, rgbPayload, rgbPayload.Length);
                    Array.Copy(response.Payload, rgbPayload.Length, rgbSignature, 0, cbSignature);

                    CounterSignature1 cs1 = new CounterSignature1(rgbSignature);
                    cs1.AddAttribute(HeaderKeys.Algorithm, ctx.Sender.SigningAlgorithm, Attributes.DO_NOT_SEND);
                    cs1.SetObject(msg);
                    cs1.SetKey(recip.SigningKey);

                    byte[] aadData = aad.EncodeToBytes();
                    cs1.SetExternalData(aadData);
                    msg.SetEncryptedContent(rgbPayload);

                    try {
                        if (!msg.Validate(cs1))
                        {
                            return;
                        }
                    }
                    catch (CoseException e) {
                        // try the next possible one
                        return;
                    }
                }

                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();

                _Log.Info($"Inner message for OSCORE{Utils.ToString(decryptedReq)}");

                response.Payload = decryptedReq.Payload;
                response.Code    = (int)decryptedReq.StatusCode;

                RestoreOptions(response, decryptedReq);
                if (decryptedReq.HasOption(OptionType.Observe))
                {
                    if (partialIV.Length > 3)
                    {
                        byte[] x = new byte[3];
                        Array.Copy(partialIV, partialIV.Length - 3, x, 0, 3);
                        partialIV = x;
                    }
                    response.AddOption(Option.Create(OptionType.Observe, partialIV));
                }

                _Log.Info($"Outgoing message for OSCORE{Utils.ToString(response)}");
            }
            base.ReceiveResponse(nextLayer, exchange, response);
        }