Ejemplo n.º 1
0
        /// <summary>
        /// Given a first message in the Edhoc protocol, parse the message into pieces
        /// and fill in the data struture elements to continue processing.
        /// Throw an exception on failures.
        /// </summary>
        /// <param name="msgData"></param>
        /// <returns></returns>
        public static EdhocResponder ParseMessage1(byte[] msgData)
        {
            EdhocResponder edhoc = new EdhocResponder();
            CBORObject     msg   = CBORObject.DecodeFromBytes(msgData);

            if (msg.Type != CBORType.Array)
            {
                throw new Exception("Invalid message");
            }
            if (msg[0].AsInt32() == 1)
            {
                edhoc._fSymmetricSecret = false;
            }
            else if (msg[0].AsInt32() == 4)
            {
                edhoc._fSymmetricSecret = true;
            }
            else
            {
                throw new Exception("Invalid Message");
            }

            // Fill in "their" data into the different arrays

            edhoc._Messages[0] = msgData;               // message_1

            edhoc._SessionId[1] = msg[1].GetByteString();
            edhoc._Nonce[1]     = msg[2].GetByteString();
            edhoc._Keys[1]      = new OneKey(msg[3]);   // Their one time key
            edhoc._algKeyAgree  = _SelectAlgorithm(msg[4], new CBORObject[] { AlgorithmValues.ECDH_SS_HKDF_256 });
            edhoc._algAEAD      = _SelectAlgorithm(msg[5], new CBORObject[] { AlgorithmValues.AES_CCM_64_64_128 });
            if (!edhoc._fSymmetricSecret)
            {
                edhoc._algSign = _SelectAlgorithm(msg[6], new CBORObject[] { AlgorithmValues.ECDSA_256 });
            }
            else
            {
                edhoc._kid[1] = msg[6];
            }

            edhoc._Keys[0] = OneKey.GenerateKey(null, edhoc._Keys[1][CoseKeyKeys.KeyType], "X25519" /*edhoc._Keys[1][CoseKeyParameterKeys.EC_Curve].AsString()*/);

#if true
            edhoc._SessionId[0] = new byte[2];
            edhoc._random.NextBytes(edhoc._SessionId[0]);
            edhoc._Nonce[0] = new byte[8];
            edhoc._random.NextBytes(edhoc._Nonce[0]);
#else
            edhoc._SessionId[0] = Encoding.UTF8.GetBytes("Kid Svr");
            edhoc._Nonce[0]     = Encoding.UTF8.GetBytes("Server Nonce");
#endif

            MessageList.Add(new ListKey(edhoc._SessionId[0]), edhoc);

            return(edhoc);
        }
Ejemplo n.º 2
0
        static public EdhocResponder ParseMessage3(byte[] msgData, KeySet serverKeys)
        {
            CBORObject algVerify = null;

            CBORObject msg = CBORObject.DecodeFromBytes(msgData);

            if (msg.Type != CBORType.Array)
            {
                throw new Exception("Invalid message");
            }

            EdhocResponder edhoc = MessageList[new ListKey(msg[1].GetByteString())];

            edhoc._Messages[2] = msgData;

            if (edhoc._fSymmetricSecret)
            {
                if (msg[0].AsInt16() != 6)
                {
                    throw new Exception("Invalid Message");
                }
            }
            else
            {
                if (msg[0].AsInt16() != 3)
                {
                    throw new Exception("Invalid Message");
                }
            }


            Encrypt0Message enc0 = (Encrypt0Message)Com.AugustCellars.COSE.Message.DecodeFromBytes(msg[2].GetByteString(), Tags.Encrypt0);

            msg.Remove(msg[2]);

            byte[] data_3 = msg.EncodeToBytes();
            byte[] aad_3  = ConcatenateAndHash(new byte[][] { edhoc._LastMessageAuthenticator, data_3 }, edhoc._MessageDigest);

            byte[][] useKeys = _DeriveKeys(edhoc._Keys, edhoc._SecretSalt, aad_3, edhoc._algAEAD);
            byte[]   encKey  = useKeys[0];

            enc0.AddAttribute(HeaderKeys.Algorithm, edhoc._algAEAD, Attributes.DO_NOT_SEND);
            enc0.AddAttribute(HeaderKeys.IV, CBORObject.FromObject(useKeys[1]), Attributes.DO_NOT_SEND);
            enc0.SetExternalData(aad_3);
            byte[] body = enc0.Decrypt(encKey);

            if (!edhoc._fSymmetricSecret)
            {
                CBORObject encBody = CBORObject.DecodeFromBytes(body);

                Sign1Message sign1 = (Sign1Message)Com.AugustCellars.COSE.Message.DecodeFromBytes(encBody[0].GetByteString(), Tags.Sign1);
                sign1.AddAttribute(HeaderKeys.Algorithm, edhoc._algSign, Attributes.DO_NOT_SEND);

                CBORObject kidObject = sign1.FindAttribute(HeaderKeys.KeyId);
                byte[]     kid       = null;
                if (kidObject != null)
                {
                    kid = kidObject.GetByteString();
                }
                sign1.SetExternalData(aad_3);

                KeySet keys = new KeySet();
                foreach (OneKey sigKey in serverKeys)
                {
                    if (sigKey.HasKid(kid))
                    {
                        keys.AddKey(sigKey);
                    }
                }

                List <OneKey> ks  = new List <OneKey>();
                List <OneKey> ks2 = ks.Where(f => f.HasKid(kid)).ToList();

                OneKey signingKey = null;
                foreach (OneKey sigKey in keys)
                {
                    try {
                        sign1.Validate(sigKey);
                        signingKey = sigKey;
                    }
                    catch (Exception) {
                        // nop;
                    }
                }

                if (signingKey == null)
                {
                    throw new Exception("Unable to complete - no signing key found");
                }
            }
            else
            {
                // body is the EXT_3 value
            }

            edhoc._LastMessageAuthenticator = ConcatenateAndHash(new byte[][] { edhoc._LastMessageAuthenticator, msgData }, edhoc._MessageDigest);

            return(edhoc);
        }
Ejemplo n.º 3
0
        protected override void DoPost(CoapExchange exchange)
        {
            byte[]         body = exchange.Request.Payload;
            EdhocResponder edhoc;

            try {
                switch (body[1] & 0xf)
                {
                case 1:
                    edhoc            = EdhocResponder.ParseMessage1(body);
                    edhoc.SigningKey = _signKey;
                    body             = edhoc.CreateMessage2();
                    exchange.Respond(CoAP.StatusCode.Changed, body);
                    break;

                case 4:
                    edhoc = EdhocResponder.ParseMessage1(body);
                    OneKey y = null;
                    foreach (OneKey x in _allKeys)
                    {
                        if (x.ContainsName(CoseKeyKeys.KeyIdentifier))
                        {
                            if (x.HasKid(edhoc.KeyIdentifier))
                            {
                                if (y != null)
                                {
                                    exchange.Respond(CoAP.StatusCode.BadRequest);
                                    return;
                                }
                                y = new OneKey(x.AsCBOR());
                            }
                        }
                    }

                    if (y == null)
                    {
                        exchange.Respond(CoAP.StatusCode.BadRequest);
                        return;
                    }

                    if (!y[CoseKeyKeys.KeyType].Equals(GeneralValues.KeyType_Octet))
                    {
                        exchange.Respond(CoAP.StatusCode.BadRequest);
                        return;
                    }

                    edhoc.SharedSecret = y;

                    body = edhoc.CreateMessage2();
                    exchange.Respond(CoAP.StatusCode.Changed, body);
                    break;

                case 3:
                    edhoc = EdhocResponder.ParseMessage3(body, _allKeys);
                    exchange.Respond(StatusCode.Changed);

                    OSCOAP.SecurityContext ctx = edhoc.CreateSecurityContext();
                    OSCOAP.SecurityContextSet.AllContexts.Add(ctx);
                    break;

                case 6:
                    edhoc = EdhocResponder.ParseMessage3(body, _allKeys);
                    exchange.Respond(CoAP.StatusCode.Changed);

                    OSCOAP.SecurityContext ctx2 = edhoc.CreateSecurityContext();
                    OSCOAP.SecurityContextSet.AllContexts.Add(ctx2);
                    break;

                default:
                    exchange.Respond(CoAP.StatusCode.BadRequest);
                    break;
                }
            }
            catch (Exception e) {
                CBORObject obj = CBORObject.NewArray();
                obj.Add(0);
                obj.Add(e.ToString());
                exchange.Respond(CoAP.StatusCode.Content, obj.EncodeToBytes());
            }
        }