initial commit
This commit is contained in:
267
lib/NimBLE-Arduino/src/nimble/CODING_STANDARDS.md
Normal file
267
lib/NimBLE-Arduino/src/nimble/CODING_STANDARDS.md
Normal file
@@ -0,0 +1,267 @@
|
||||
# Coding Style for Apache NimBLE
|
||||
|
||||
Apache NimBLE project is part of Apache Mynewt projct and follows its coding
|
||||
style.
|
||||
|
||||
# Coding Style for Apache Mynewt Core
|
||||
|
||||
This document is meant to define the coding style for Apache Mynewt, and
|
||||
all subprojects of Apache Mynewt. This covers C and Assembly coding
|
||||
conventions, *only*. Other languages (such as Go), have their own
|
||||
coding conventions.
|
||||
|
||||
## Headers
|
||||
|
||||
* All files that are newly written, should have the Apache License clause
|
||||
at the top of them.
|
||||
|
||||
* For files that are copied from another source, but contain an Apache
|
||||
compatible license, the original license header shall be maintained.
|
||||
|
||||
* For more information on applying the Apache license, the definitive
|
||||
source is here: http://www.apache.org/dev/apply-license.html
|
||||
|
||||
* The Apache License clause for the top of files is as follows:
|
||||
|
||||
```no-highlight
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
```
|
||||
|
||||
## Whitespace and Braces
|
||||
|
||||
* Code must be indented to 4 spaces, tabs should not be used.
|
||||
|
||||
* Do not add whitespace at the end of a line.
|
||||
|
||||
* Put space after keywords (for, if, return, switch, while).
|
||||
|
||||
* for, else, if, while statements must have braces around their
|
||||
code blocks, i.e., do:
|
||||
|
||||
```
|
||||
if (x) {
|
||||
assert(0);
|
||||
} else {
|
||||
assert(0);
|
||||
}
|
||||
```
|
||||
|
||||
Not:
|
||||
|
||||
```
|
||||
if (x)
|
||||
assert(0);
|
||||
else
|
||||
assert(0);
|
||||
```
|
||||
|
||||
* Braces for statements must be on the same line as the statement. Good:
|
||||
|
||||
```
|
||||
for (i = 0; i < 10; i++) {
|
||||
if (i == 5) {
|
||||
break;
|
||||
} else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Not:
|
||||
|
||||
```
|
||||
for (i = 0; i < 10; i++)
|
||||
{ <-- brace must be on same line as for
|
||||
if (i == 5) {
|
||||
break;
|
||||
} <-- no new line between else
|
||||
else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
* After a function declaration, the braces should be on a newline, i.e. do:
|
||||
|
||||
```
|
||||
static void *
|
||||
function(int var1, int var2)
|
||||
{
|
||||
```
|
||||
|
||||
not:
|
||||
|
||||
```
|
||||
static void *
|
||||
function(int var1, int var2) {
|
||||
```
|
||||
|
||||
## Line Length and Wrap
|
||||
|
||||
* Line length should never exceed 79 columns.
|
||||
|
||||
* When you have to wrap a long statement, put the operator at the end of the
|
||||
line. i.e.:
|
||||
|
||||
```
|
||||
if (x &&
|
||||
y == 10 &&
|
||||
b)
|
||||
```
|
||||
|
||||
Not:
|
||||
|
||||
```
|
||||
if (x
|
||||
&& y == 10
|
||||
&& b)
|
||||
```
|
||||
|
||||
## Comments
|
||||
|
||||
* No C++ style comments allowed.
|
||||
|
||||
* When using a single line comment, put it above the line of code that you
|
||||
intend to comment, i.e., do:
|
||||
|
||||
```
|
||||
/* check variable */
|
||||
if (a) {
|
||||
```
|
||||
|
||||
Not:
|
||||
|
||||
```
|
||||
if (a) { /* check variable */
|
||||
```
|
||||
|
||||
|
||||
* All public APIs should be commented with Doxygen style comments describing
|
||||
purpose, parameters and return values. Private APIs need not be documented.
|
||||
|
||||
|
||||
## Header files
|
||||
|
||||
* Header files must contain the following structure:
|
||||
* Apache License (see above)
|
||||
* ```#ifdef``` aliasing, to prevent multiple includes
|
||||
* ```#include``` directives for other required header files
|
||||
* ```#ifdef __cplusplus``` wrappers to maintain C++ friendly APIs
|
||||
* Contents of the header file
|
||||
|
||||
* ```#ifdef``` aliasing, shall be in the following format, where
|
||||
the package name is "os" and the file name is "callout.h":
|
||||
|
||||
```no-highlight
|
||||
#ifndef _OS_CALLOUT_H
|
||||
#define _OS_CALLOUT_H
|
||||
```
|
||||
|
||||
* ```#include``` directives must happen prior to the cplusplus
|
||||
wrapper.
|
||||
|
||||
* The cplusplus wrapper must have the following format, and precedes
|
||||
any contents of the header file:
|
||||
|
||||
```no-highlight
|
||||
#ifdef __cplusplus
|
||||
#extern "C" {
|
||||
##endif
|
||||
```
|
||||
|
||||
## Naming
|
||||
|
||||
* Names of functions, structures and variables must be in all lowercase.
|
||||
|
||||
* Names should be as short as possible, but no shorter.
|
||||
|
||||
* Globally visible names must be prefixed with the name of the module,
|
||||
followed by the '_' character, i.e.:
|
||||
|
||||
```
|
||||
os_callout_init(&c)
|
||||
```
|
||||
|
||||
Not:
|
||||
|
||||
```
|
||||
callout_init(c)
|
||||
```
|
||||
|
||||
## Functions
|
||||
|
||||
* No spaces after function names when calling a function, i.e, do:
|
||||
|
||||
```
|
||||
rc = function(a)
|
||||
```
|
||||
|
||||
Not:
|
||||
|
||||
```
|
||||
rc = function (a)
|
||||
```
|
||||
|
||||
|
||||
* Arguments to function calls should have spaces between the comma, i.e. do:
|
||||
|
||||
```
|
||||
rc = function(a, b)
|
||||
```
|
||||
|
||||
Not:
|
||||
|
||||
```
|
||||
rc = function(a,b)
|
||||
```
|
||||
|
||||
* The function type must be on a line by itself preceding the function, i.e. do:
|
||||
|
||||
```
|
||||
static void *
|
||||
function(int var1, int var2)
|
||||
{
|
||||
```
|
||||
|
||||
Not:
|
||||
|
||||
```
|
||||
static void *function(int var1, int var2)
|
||||
{
|
||||
```
|
||||
|
||||
* In general, for functions that return values that denote success or error, 0
|
||||
shall be success, and non-zero shall be the failure code.
|
||||
|
||||
## Variables and Macros
|
||||
|
||||
* Do not use typedefs for structures. This makes it impossible for
|
||||
applications to use pointers to those structures opaquely.
|
||||
|
||||
* typedef may be used for non-structure types, where it is beneficial to
|
||||
hide or alias the underlying type used (e.g. ```os_time_t```.) Indicate
|
||||
typedefs by applying the ```_t``` marker to them.
|
||||
|
||||
* Place all function-local variable definitions at the top of the function body, before any statements.
|
||||
|
||||
## Compiler Directives
|
||||
|
||||
* Code must compile cleanly with -Wall enabled.
|
||||
|
||||
217
lib/NimBLE-Arduino/src/nimble/LICENSE
Normal file
217
lib/NimBLE-Arduino/src/nimble/LICENSE
Normal file
@@ -0,0 +1,217 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
|
||||
END OF TERMS AND CONDITIONS
|
||||
|
||||
APPENDIX: How to apply the Apache License to your work.
|
||||
|
||||
To apply the Apache License to your work, attach the following
|
||||
boilerplate notice, with the fields enclosed by brackets "{}"
|
||||
replaced with your own identifying information. (Don't include
|
||||
the brackets!) The text should be enclosed in the appropriate
|
||||
comment syntax for the file format. We also recommend that a
|
||||
file or class name and description of purpose be included on the
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright {yyyy} {name of copyright owner}
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
||||
This product bundles queue.h 8.5, which is available under the "3-clause BSD"
|
||||
license. For details, see porting/nimble/include/os/queue.h
|
||||
|
||||
This product partly derives from FreeBSD, which is available under the
|
||||
"3-clause BSD" license. For details, see:
|
||||
* porting/nimble/src/os_mbuf.c
|
||||
|
||||
This product bundles Gary S. Brown's CRC32 implementation, which is available
|
||||
under the following license:
|
||||
COPYRIGHT (C) 1986 Gary S. Brown. You may use this program, or
|
||||
code or tables extracted from it, as desired without restriction.
|
||||
|
||||
This product bundles tinycrypt, which is available under the "3-clause BSD"
|
||||
license. For details, and bundled files see:
|
||||
* ext/tinycrypt/LICENSE
|
||||
9
lib/NimBLE-Arduino/src/nimble/NOTICE
Normal file
9
lib/NimBLE-Arduino/src/nimble/NOTICE
Normal file
@@ -0,0 +1,9 @@
|
||||
Apache Mynewt NimBLE
|
||||
Copyright 2015-2020 The Apache Software Foundation
|
||||
Modifications Copyright 2017-2020 Espressif Systems (Shanghai) CO., LTD.
|
||||
|
||||
This product includes software developed at
|
||||
The Apache Software Foundation (http://www.apache.org/).
|
||||
|
||||
Portions of this software were developed at
|
||||
Runtime Inc, copyright 2015.
|
||||
169
lib/NimBLE-Arduino/src/nimble/README.md
Normal file
169
lib/NimBLE-Arduino/src/nimble/README.md
Normal file
@@ -0,0 +1,169 @@
|
||||
<!--
|
||||
#
|
||||
# Licensed to the Apache Software Foundation (ASF) under one
|
||||
# or more contributor license agreements. See the NOTICE file
|
||||
# distributed with this work for additional information
|
||||
# regarding copyright ownership. The ASF licenses this file
|
||||
# to you under the Apache License, Version 2.0 (the
|
||||
# "License"); you may not use this file except in compliance
|
||||
# with the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing,
|
||||
# software distributed under the License is distributed on an
|
||||
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
#
|
||||
-->
|
||||
|
||||
<img src="http://mynewt.apache.org/img/logo.svg" width="250" alt="Apache Mynewt">
|
||||
|
||||
## Overview
|
||||
|
||||
Apache NimBLE is an open-source Bluetooth 5.1 stack (both Host & Controller)
|
||||
that completely replaces the proprietary SoftDevice on Nordic chipsets. It is
|
||||
part of [Apache Mynewt project](https://github.com/apache/mynewt-core).
|
||||
|
||||
Features highlight:
|
||||
- Support for 251 byte packet size
|
||||
- Support for all 4 roles concurrently - Broadcaster, Observer, Peripheral and Central
|
||||
- Support for up to 32 simultaneous connections.
|
||||
- Legacy and SC (secure connections) SMP support (pairing and bonding).
|
||||
- Advertising Extensions.
|
||||
- Coded (aka Long Range) and 2M PHYs.
|
||||
- Bluetooth Mesh.
|
||||
|
||||
## Supported hardware
|
||||
|
||||
Controller supports Nordic nRF51 and nRF52 chipsets. Host runs on any board
|
||||
and architecture [supported](https://github.com/apache/mynewt-core#overview)
|
||||
by Apache Mynewt OS.
|
||||
|
||||
|
||||
## Browsing
|
||||
|
||||
If you are browsing around the source tree, and want to see some of the
|
||||
major functional chunks, here are a few pointers:
|
||||
|
||||
- nimble/controller: Contains code for controller including Link Layer and HCI implementation
|
||||
([controller](https://github.com/apache/mynewt-nimble/tree/master/nimble/controller))
|
||||
|
||||
- nimble/drivers: Contains drivers for supported radio transceivers (Nordic nRF51 and nRF52)
|
||||
([drivers](https://github.com/apache/mynewt-nimble/tree/master/nimble/drivers))
|
||||
|
||||
- nimble/host: Contains code for host subsystem. This includes protocols like
|
||||
L2CAP and ATT, support for HCI commands and events, Generic Access Profile (GAP),
|
||||
Generic Attribute Profile (GATT) and Security Manager (SM).
|
||||
([host](https://github.com/apache/mynewt-nimble/tree/master/nimble/host))
|
||||
|
||||
- nimble/host/mesh: Contains code for Bluetooth Mesh subsystem.
|
||||
([mesh](https://github.com/apache/mynewt-nimble/tree/master/nimble/host/mesh))
|
||||
|
||||
- nimble/transport: Contains code for supported transport protocols between host
|
||||
and controller. This includes UART, emSPI and RAM (used in combined build when
|
||||
host and controller run on same CPU)
|
||||
([transport](https://github.com/apache/mynewt-nimble/tree/master/nimble/transport))
|
||||
|
||||
- porting: Contains implementation of NimBLE Porting Layer (NPL) for supported
|
||||
operating systems
|
||||
([porting](https://github.com/apache/mynewt-nimble/tree/master/porting))
|
||||
|
||||
- ext: Contains external libraries used by NimBLE. Those are used if not
|
||||
provided by OS
|
||||
([ext](https://github.com/apache/mynewt-nimble/tree/master/ext))
|
||||
|
||||
- kernel: Contains the core of the RTOS ([kernel/os](https://github.com/apache/mynewt-core/tree/master/kernel/os))
|
||||
|
||||
## Sample Applications
|
||||
|
||||
There are also some sample applications that show how to Apache Mynewt NimBLE
|
||||
stack. These sample applications are located in the `apps/` directory of
|
||||
Apache Mynewt [repo](https://github.com/apache/mynewt-core). Some examples:
|
||||
|
||||
* [blecent](https://github.com/apache/mynewt-nimble/tree/master/apps/blecent):
|
||||
A basic central device with no user interface. This application scans for
|
||||
a peripheral that supports the alert notification service (ANS). Upon
|
||||
discovering such a peripheral, blecent connects and performs a characteristic
|
||||
read, characteristic write, and notification subscription.
|
||||
* [blehci](https://github.com/apache/mynewt-nimble/tree/master/apps/blehci):
|
||||
Implements a BLE controller-only application. A separate host-only
|
||||
implementation, such as Linux's BlueZ, can interface with this application via
|
||||
HCI over UART.
|
||||
* [bleprph](https://github.com/apache/mynewt-nimble/tree/master/apps/bleprph): An
|
||||
implementation of a minimal BLE peripheral.
|
||||
* [btshell](https://github.com/apache/mynewt-nimble/tree/master/apps/btshell): A
|
||||
shell-like application allowing to configure and use most of NimBLE
|
||||
functionality from command line.
|
||||
* [bleuart](https://github.com/apache/mynewt-core/tree/master/apps/bleuart):
|
||||
Implements a simple BLE peripheral that supports the Nordic
|
||||
UART / Serial Port Emulation service
|
||||
(https://developer.nordicsemi.com/nRF5_SDK/nRF51_SDK_v8.x.x/doc/8.0.0/s110/html/a00072.html).
|
||||
|
||||
# Getting Help
|
||||
|
||||
If you are having trouble using or contributing to Apache Mynewt NimBLE, or just
|
||||
want to talk to a human about what you're working on, you can contact us via the
|
||||
[developers mailing list](mailto:dev@mynewt.apache.org).
|
||||
|
||||
Although not a formal channel, you can also find a number of core developers
|
||||
on the #mynewt channel on Freenode IRC or #general channel on [Mynewt Slack](https://mynewt.slack.com/join/shared_invite/enQtNjA1MTg0NzgyNzg3LTcyMmZiOGQzOGMxM2U4ODFmMTIwNjNmYTE5Y2UwYjQwZWIxNTE0MTUzY2JmMTEzOWFjYWZkNGM0YmM4MzAxNWQ)
|
||||
|
||||
Also, be sure to checkout the [Frequently Asked Questions](https://mynewt.apache.org/faq/answers)
|
||||
for some help troubleshooting first.
|
||||
|
||||
# Contributing
|
||||
|
||||
Anybody who works with Apache Mynewt can be a contributing member of the
|
||||
community that develops and deploys it. The process of releasing an operating
|
||||
system for microcontrollers is never done: and we welcome your contributions
|
||||
to that effort.
|
||||
|
||||
More information can be found at the Community section of the Apache Mynewt
|
||||
website, located [here](https://mynewt.apache.org/community).
|
||||
|
||||
## Pull Requests
|
||||
|
||||
Apache Mynewt welcomes pull request via Github. Discussions are done on Github,
|
||||
but depending on the topic, can also be relayed to the official Apache Mynewt
|
||||
developer mailing list dev@mynewt.apache.org.
|
||||
|
||||
If you are suggesting a new feature, please email the developer list directly,
|
||||
with a description of the feature you are planning to work on.
|
||||
|
||||
## Filing Bugs
|
||||
|
||||
Bugs can be filed on the
|
||||
[Apache Mynewt NimBLE Issues](https://github.com/apache/mynewt-nimble/issues).
|
||||
Please label the issue as a "Bug".
|
||||
|
||||
Where possible, please include a self-contained reproduction case!
|
||||
|
||||
## Feature Requests
|
||||
|
||||
Feature requests should also be filed on the
|
||||
[Apache Mynewt NimBLE Bug Tracker](https://github.com/apache/mynewt-nimble/issues).
|
||||
Please label the issue as a "Feature" or "Enhancement" depending on the scope.
|
||||
|
||||
## Writing Tests
|
||||
|
||||
We love getting newt tests! Apache Mynewt is a huge undertaking, and improving
|
||||
code coverage is a win for every Apache Mynewt user.
|
||||
|
||||
<!--
|
||||
TODO
|
||||
## Writing Documentation
|
||||
|
||||
Contributing to documentation (in addition to writing tests), is a great way
|
||||
to get involved with the Apache Mynewt project.
|
||||
|
||||
The Mynewt NimBLE documentation is found in [/docs](/docs).
|
||||
-->
|
||||
|
||||
# License
|
||||
|
||||
The code in this repository is all under either the Apache 2 license, or a
|
||||
license compatible with the Apache 2 license. See the LICENSE file for more
|
||||
information.
|
||||
33
lib/NimBLE-Arduino/src/nimble/RELEASE_NOTES.md
Normal file
33
lib/NimBLE-Arduino/src/nimble/RELEASE_NOTES.md
Normal file
@@ -0,0 +1,33 @@
|
||||
# RELEASE NOTES
|
||||
|
||||
18 March 2020 - Apache NimBLE v1.3.0
|
||||
|
||||
For full release notes, please visit the
|
||||
[Apache Mynewt Wiki](https://cwiki.apache.org/confluence/display/MYNEWT/Release+Notes).
|
||||
|
||||
Apache NimBLE is an open-source Bluetooth 5.1 stack (both Host & Controller) that completely
|
||||
replaces the proprietary SoftDevice on Nordic chipsets.
|
||||
|
||||
New features in this version of NimBLE include:
|
||||
|
||||
* Support for Bluetooth Core Specification 5.1
|
||||
* New blestress test application
|
||||
* Dialog DA1469x CMAC driver
|
||||
* Support for LE Secure Connections out-of-band (OOB) association model
|
||||
* Support for automated generation of syscfg for ports
|
||||
* Qualification related bugfixes
|
||||
* BLE Mesh improvements - fixes and resync with latest Zephyr code
|
||||
* RIOT OS port fixes and improvements
|
||||
* btshell sample application improvements
|
||||
* improvements for bttester application
|
||||
* Controller duplicates filtering improvements
|
||||
* Multi PHY support improvements
|
||||
* Memory and CPU usage optimizations
|
||||
* Use of packed structs for HCI (code size reduction)
|
||||
* Linux sample improvements
|
||||
* PTS test instructions updates
|
||||
* Clock managements improvements in controller
|
||||
|
||||
If working on next-generation RTOS and Bluetooth protocol stack
|
||||
sounds exciting to you, get in touch, by sending a mail to the Apache Mynewt
|
||||
Developer's list, dev@mynewt.apache.org.
|
||||
16
lib/NimBLE-Arduino/src/nimble/console/console.h
Normal file
16
lib/NimBLE-Arduino/src/nimble/console/console.h
Normal file
@@ -0,0 +1,16 @@
|
||||
#ifndef __CONSOLE_H__
|
||||
#define __CONSOLE_H__
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define console_printf printf
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __CONSOLE_H__ */
|
||||
@@ -0,0 +1,59 @@
|
||||
// Copyright 2016-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
#ifndef __ESP_COMPILER_H
|
||||
#define __ESP_COMPILER_H
|
||||
|
||||
/*
|
||||
* The likely and unlikely macro pairs:
|
||||
* These macros are useful to place when application
|
||||
* knows the majority ocurrence of a decision paths,
|
||||
* placing one of these macros can hint the compiler
|
||||
* to reorder instructions producing more optimized
|
||||
* code.
|
||||
*/
|
||||
#if (CONFIG_COMPILER_OPTIMIZATION_PERF)
|
||||
#ifndef likely
|
||||
#define likely(x) __builtin_expect(!!(x), 1)
|
||||
#endif
|
||||
#ifndef unlikely
|
||||
#define unlikely(x) __builtin_expect(!!(x), 0)
|
||||
#endif
|
||||
#else
|
||||
#ifndef likely
|
||||
#define likely(x) (x)
|
||||
#endif
|
||||
#ifndef unlikely
|
||||
#define unlikely(x) (x)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Utility macros used for designated initializers, which work differently
|
||||
* in C99 and C++ standards mainly for aggregate types.
|
||||
* The member separator, comma, is already part of the macro, please omit the trailing comma.
|
||||
* Usage example:
|
||||
* struct config_t { char* pchr; char arr[SIZE]; } config = {
|
||||
* ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_EMPTY(pchr)
|
||||
* ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_STR(arr, "Value")
|
||||
* };
|
||||
*/
|
||||
#ifdef __cplusplus
|
||||
#define ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_STR(member, value) { .member = value },
|
||||
#define ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_EMPTY(member) .member = { },
|
||||
#else
|
||||
#define ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_STR(member, value) .member = value,
|
||||
#define ESP_COMPILER_DESIGNATED_INIT_AGGREGATE_TYPE_EMPTY(member)
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
#ifndef __ESP_NIMBLE_HCI_H__
|
||||
#define __ESP_NIMBLE_HCI_H__
|
||||
|
||||
#include "nimble/nimble/include/nimble/ble_hci_trans.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define BLE_HCI_UART_H4_NONE 0x00
|
||||
#define BLE_HCI_UART_H4_CMD 0x01
|
||||
#define BLE_HCI_UART_H4_ACL 0x02
|
||||
#define BLE_HCI_UART_H4_SCO 0x03
|
||||
#define BLE_HCI_UART_H4_EVT 0x04
|
||||
|
||||
/**
|
||||
* @brief Initialize VHCI transport layer between NimBLE Host and
|
||||
* ESP Bluetooth controller
|
||||
*
|
||||
* This function initializes the transport buffers to be exchanged
|
||||
* between NimBLE host and ESP controller. It also registers required
|
||||
* host callbacks with the controller.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK if the initialization is successful
|
||||
* - Appropriate error code from esp_err_t in case of an error
|
||||
*/
|
||||
esp_err_t esp_nimble_hci_init(void);
|
||||
|
||||
/**
|
||||
* @brief Initialize ESP Bluetooth controller(link layer) and VHCI transport
|
||||
* layer between NimBLE Host and ESP Bluetooth controller
|
||||
*
|
||||
* This function initializes ESP controller in BLE only mode and the
|
||||
* transport buffers to be exchanged between NimBLE host and ESP controller.
|
||||
* It also registers required host callbacks with the controller.
|
||||
*
|
||||
* Below is the sequence of APIs to be called to initialize/enable NimBLE host and ESP controller:
|
||||
*
|
||||
* @code{c}
|
||||
* void ble_host_task(void *param)
|
||||
* {
|
||||
* nimble_port_run(); //This function will return only when nimble_port_stop() is executed.
|
||||
* nimble_port_freertos_deinit();
|
||||
* }
|
||||
*
|
||||
* int ret = esp_nimble_hci_and_controller_init();
|
||||
* if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "esp_nimble_hci_and_controller_init() failed with error: %d", ret);
|
||||
* return;
|
||||
* }
|
||||
*
|
||||
* nimble_port_init();
|
||||
*
|
||||
* //Initialize the NimBLE Host configuration
|
||||
*
|
||||
* nimble_port_freertos_init(ble_host_task);
|
||||
* @endcode
|
||||
*
|
||||
* nimble_port_freertos_init() is an optional call that creates a new task in which the NimBLE
|
||||
* host will run. The task function should have a call to nimble_port_run(). If a separate task
|
||||
* is not required, calling nimble_port_run() will run the NimBLE host in the current task.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK if the initialization is successful
|
||||
* - Appropriate error code from esp_err_t in case of an error
|
||||
*/
|
||||
esp_err_t esp_nimble_hci_and_controller_init(void);
|
||||
|
||||
/**
|
||||
* @brief Deinitialize VHCI transport layer between NimBLE Host and
|
||||
* ESP Bluetooth controller
|
||||
*
|
||||
* @note This function should be called after the NimBLE host is deinitialized.
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK if the deinitialization is successful
|
||||
* - Appropriate error codes from esp_err_t in case of an error
|
||||
*/
|
||||
esp_err_t esp_nimble_hci_deinit(void);
|
||||
|
||||
/**
|
||||
* @brief Deinitialize VHCI transport layer between NimBLE Host and
|
||||
* ESP Bluetooth controller and disable and deinitialize the controller
|
||||
*
|
||||
* @note This function should not be executed in the context of Bluetooth host task.
|
||||
*
|
||||
* @note This function should be called after the NimBLE host is deinitialized.
|
||||
*
|
||||
* Below is the sequence of APIs to be called to disable/deinit NimBLE host and ESP controller:
|
||||
*
|
||||
* @code{c}
|
||||
* int ret = nimble_port_stop();
|
||||
* if (ret == 0) {
|
||||
* nimble_port_deinit();
|
||||
*
|
||||
* ret = esp_nimble_hci_and_controller_deinit();
|
||||
* if (ret != ESP_OK) {
|
||||
ESP_LOGE(TAG, "esp_nimble_hci_and_controller_deinit() failed with error: %d", ret);
|
||||
* }
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* If nimble_port_freertos_init() is used during initialization, then
|
||||
* nimble_port_freertos_deinit() should be called in the host task after nimble_port_run().
|
||||
*
|
||||
* @return
|
||||
* - ESP_OK if the deinitialization is successful
|
||||
* - Appropriate error codes from esp_err_t in case of an error
|
||||
*/
|
||||
esp_err_t esp_nimble_hci_and_controller_deinit(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __ESP_NIMBLE_HCI_H__ */
|
||||
#endif
|
||||
@@ -0,0 +1,583 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
|
||||
#include <assert.h>
|
||||
#include "nimble/porting/nimble/include/sysinit/sysinit.h"
|
||||
#include "nimble/nimble/include/nimble/hci_common.h"
|
||||
#include "nimble/nimble/host/include/host/ble_hs.h"
|
||||
#include "nimble/porting/nimble/include/nimble/nimble_port.h"
|
||||
#include "nimble/porting/npl/freertos/include/nimble/nimble_port_freertos.h"
|
||||
#include "../include/esp_nimble_hci.h"
|
||||
#include "../../port/include/esp_nimble_mem.h"
|
||||
#include <esp_bt.h>
|
||||
#include <freertos/semphr.h>
|
||||
#include "../include/esp_compiler.h"
|
||||
/* IPC is used to improve performance when calls come from a processor not running the NimBLE stack */
|
||||
/* but does not exist for solo */
|
||||
#ifndef CONFIG_FREERTOS_UNICORE
|
||||
#include "esp_ipc.h"
|
||||
#endif
|
||||
|
||||
#define NIMBLE_VHCI_TIMEOUT_MS 2000
|
||||
#define BLE_HCI_EVENT_HDR_LEN (2)
|
||||
#define BLE_HCI_CMD_HDR_LEN (3)
|
||||
|
||||
static ble_hci_trans_rx_cmd_fn *ble_hci_rx_cmd_hs_cb;
|
||||
static void *ble_hci_rx_cmd_hs_arg;
|
||||
|
||||
static ble_hci_trans_rx_acl_fn *ble_hci_rx_acl_hs_cb;
|
||||
static void *ble_hci_rx_acl_hs_arg;
|
||||
|
||||
static struct os_mbuf_pool ble_hci_acl_mbuf_pool;
|
||||
static struct os_mempool_ext ble_hci_acl_pool;
|
||||
/*
|
||||
* The MBUF payload size must accommodate the HCI data header size plus the
|
||||
* maximum ACL data packet length. The ACL block size is the size of the
|
||||
* mbufs we will allocate.
|
||||
*/
|
||||
#define ACL_BLOCK_SIZE OS_ALIGN(MYNEWT_VAL(BLE_ACL_BUF_SIZE) \
|
||||
+ BLE_MBUF_MEMBLOCK_OVERHEAD \
|
||||
+ BLE_HCI_DATA_HDR_SZ, OS_ALIGNMENT)
|
||||
|
||||
static os_membuf_t *ble_hci_acl_buf;
|
||||
|
||||
static struct os_mempool ble_hci_cmd_pool;
|
||||
static os_membuf_t *ble_hci_cmd_buf;
|
||||
|
||||
static struct os_mempool ble_hci_evt_hi_pool;
|
||||
static os_membuf_t *ble_hci_evt_hi_buf;
|
||||
|
||||
static struct os_mempool ble_hci_evt_lo_pool;
|
||||
static os_membuf_t *ble_hci_evt_lo_buf;
|
||||
|
||||
static SemaphoreHandle_t vhci_send_sem;
|
||||
const static char *TAG = "NimBLE";
|
||||
|
||||
int os_msys_buf_alloc(void);
|
||||
void os_msys_buf_free(void);
|
||||
|
||||
void ble_hci_trans_cfg_hs(ble_hci_trans_rx_cmd_fn *cmd_cb,
|
||||
void *cmd_arg,
|
||||
ble_hci_trans_rx_acl_fn *acl_cb,
|
||||
void *acl_arg)
|
||||
{
|
||||
ble_hci_rx_cmd_hs_cb = cmd_cb;
|
||||
ble_hci_rx_cmd_hs_arg = cmd_arg;
|
||||
ble_hci_rx_acl_hs_cb = acl_cb;
|
||||
ble_hci_rx_acl_hs_arg = acl_arg;
|
||||
}
|
||||
|
||||
/* Added; Called from the core NimBLE is running on, not used for unicore */
|
||||
#ifndef CONFIG_FREERTOS_UNICORE
|
||||
void ble_hci_trans_hs_cmd_tx_on_core(void *arg)
|
||||
{
|
||||
// Ugly but necessary as the arduino core does not provide enough IPC stack for variables.
|
||||
esp_vhci_host_send_packet((uint8_t*)arg, *((uint8_t*)arg + 3) + 1 + BLE_HCI_CMD_HDR_LEN);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Modified to use ipc calls in arduino to correct performance issues */
|
||||
int ble_hci_trans_hs_cmd_tx(uint8_t *cmd)
|
||||
{
|
||||
uint16_t len;
|
||||
uint8_t rc = 0;
|
||||
|
||||
assert(cmd != NULL);
|
||||
*cmd = BLE_HCI_UART_H4_CMD;
|
||||
len = BLE_HCI_CMD_HDR_LEN + cmd[3] + 1;
|
||||
if (!esp_vhci_host_check_send_available()) {
|
||||
ESP_LOGD(TAG, "Controller not ready to receive packets");
|
||||
}
|
||||
|
||||
if (xSemaphoreTake(vhci_send_sem, NIMBLE_VHCI_TIMEOUT_MS / portTICK_PERIOD_MS) == pdTRUE) {
|
||||
/* esp_ipc_call_blocking does not exist for solo */
|
||||
#ifndef CONFIG_FREERTOS_UNICORE
|
||||
if (xPortGetCoreID() != CONFIG_BT_NIMBLE_PINNED_TO_CORE && !xPortInIsrContext()) {
|
||||
esp_ipc_call_blocking(CONFIG_BT_NIMBLE_PINNED_TO_CORE,
|
||||
ble_hci_trans_hs_cmd_tx_on_core, cmd);
|
||||
} else {
|
||||
esp_vhci_host_send_packet(cmd, len);
|
||||
}
|
||||
#else /* Unicore */
|
||||
esp_vhci_host_send_packet(cmd, len);
|
||||
#endif
|
||||
} else {
|
||||
rc = BLE_HS_ETIMEOUT_HCI;
|
||||
}
|
||||
|
||||
ble_hci_trans_buf_free(cmd);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int ble_hci_trans_ll_evt_tx(uint8_t *hci_ev)
|
||||
{
|
||||
int rc = ESP_FAIL;
|
||||
|
||||
if (ble_hci_rx_cmd_hs_cb) {
|
||||
rc = ble_hci_rx_cmd_hs_cb(hci_ev, ble_hci_rx_cmd_hs_arg);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/* Added; Called from the core NimBLE is running on, not used for unicore */
|
||||
#ifndef CONFIG_FREERTOS_UNICORE
|
||||
void ble_hci_trans_hs_acl_tx_on_core(void *arg)
|
||||
{
|
||||
// Ugly but necessary as the arduino core does not provide enough IPC stack for variables.
|
||||
esp_vhci_host_send_packet((uint8_t*)arg + 2, *(uint16_t*)arg);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Modified to use ipc calls in arduino to correct performance issues */
|
||||
int ble_hci_trans_hs_acl_tx(struct os_mbuf *om)
|
||||
{
|
||||
uint16_t len = 0;
|
||||
uint8_t data[MYNEWT_VAL(BLE_ACL_BUF_SIZE) + 3], rc = 0;
|
||||
bool tx_using_nimble_core = 0;
|
||||
/* If this packet is zero length, just free it */
|
||||
if (OS_MBUF_PKTLEN(om) == 0) {
|
||||
os_mbuf_free_chain(om);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!esp_vhci_host_check_send_available()) {
|
||||
ESP_LOGD(TAG, "Controller not ready to receive packets");
|
||||
}
|
||||
|
||||
len = 1 + OS_MBUF_PKTLEN(om);
|
||||
/* Don't check core ID if unicore */
|
||||
#ifndef CONFIG_FREERTOS_UNICORE
|
||||
tx_using_nimble_core = xPortGetCoreID() != CONFIG_BT_NIMBLE_PINNED_TO_CORE;
|
||||
if (tx_using_nimble_core && !xPortInIsrContext()) {
|
||||
data[0] = len;
|
||||
data[1] = (len >> 8);
|
||||
data[2] = BLE_HCI_UART_H4_ACL;
|
||||
os_mbuf_copydata(om, 0, OS_MBUF_PKTLEN(om), &data[3]);
|
||||
} else {
|
||||
data[0] = BLE_HCI_UART_H4_ACL;
|
||||
os_mbuf_copydata(om, 0, OS_MBUF_PKTLEN(om), &data[1]);
|
||||
}
|
||||
#else /* Unicore */
|
||||
data[0] = BLE_HCI_UART_H4_ACL;
|
||||
os_mbuf_copydata(om, 0, OS_MBUF_PKTLEN(om), &data[1]);
|
||||
#endif
|
||||
|
||||
if (xSemaphoreTake(vhci_send_sem, NIMBLE_VHCI_TIMEOUT_MS / portTICK_PERIOD_MS) == pdTRUE) {
|
||||
/* esp_ipc_call_blocking does not exist for solo */
|
||||
#ifndef CONFIG_FREERTOS_UNICORE
|
||||
if (tx_using_nimble_core && !xPortInIsrContext()) {
|
||||
esp_ipc_call_blocking(CONFIG_BT_NIMBLE_PINNED_TO_CORE,
|
||||
ble_hci_trans_hs_acl_tx_on_core, data);
|
||||
} else {
|
||||
esp_vhci_host_send_packet(data, len);
|
||||
}
|
||||
#else /* Unicore */
|
||||
esp_vhci_host_send_packet(data, len);
|
||||
#endif
|
||||
} else {
|
||||
rc = BLE_HS_ETIMEOUT_HCI;
|
||||
}
|
||||
|
||||
os_mbuf_free_chain(om);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int ble_hci_trans_ll_acl_tx(struct os_mbuf *om)
|
||||
{
|
||||
int rc = ESP_FAIL;
|
||||
|
||||
if (ble_hci_rx_acl_hs_cb) {
|
||||
rc = ble_hci_rx_acl_hs_cb(om, ble_hci_rx_acl_hs_arg);
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
uint8_t *ble_hci_trans_buf_alloc(int type)
|
||||
{
|
||||
uint8_t *buf;
|
||||
|
||||
switch (type) {
|
||||
case BLE_HCI_TRANS_BUF_CMD:
|
||||
buf = os_memblock_get(&ble_hci_cmd_pool);
|
||||
break;
|
||||
|
||||
case BLE_HCI_TRANS_BUF_EVT_HI:
|
||||
buf = os_memblock_get(&ble_hci_evt_hi_pool);
|
||||
if (buf == NULL) {
|
||||
/* If no high-priority event buffers remain, try to grab a
|
||||
* low-priority one.
|
||||
*/
|
||||
buf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_LO);
|
||||
}
|
||||
break;
|
||||
|
||||
case BLE_HCI_TRANS_BUF_EVT_LO:
|
||||
buf = os_memblock_get(&ble_hci_evt_lo_pool);
|
||||
break;
|
||||
|
||||
default:
|
||||
assert(0);
|
||||
buf = NULL;
|
||||
}
|
||||
|
||||
return buf;
|
||||
}
|
||||
|
||||
void ble_hci_trans_buf_free(uint8_t *buf)
|
||||
{
|
||||
int rc;
|
||||
/* XXX: this may look a bit odd, but the controller uses the command
|
||||
* buffer to send back the command complete/status as an immediate
|
||||
* response to the command. This was done to insure that the controller
|
||||
* could always send back one of these events when a command was received.
|
||||
* Thus, we check to see which pool the buffer came from so we can free
|
||||
* it to the appropriate pool
|
||||
*/
|
||||
if (os_memblock_from(&ble_hci_evt_hi_pool, buf)) {
|
||||
rc = os_memblock_put(&ble_hci_evt_hi_pool, buf);
|
||||
assert(rc == 0);
|
||||
} else if (os_memblock_from(&ble_hci_evt_lo_pool, buf)) {
|
||||
rc = os_memblock_put(&ble_hci_evt_lo_pool, buf);
|
||||
assert(rc == 0);
|
||||
} else {
|
||||
assert(os_memblock_from(&ble_hci_cmd_pool, buf));
|
||||
rc = os_memblock_put(&ble_hci_cmd_pool, buf);
|
||||
assert(rc == 0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Unsupported; the RAM transport does not have a dedicated ACL data packet
|
||||
* pool.
|
||||
*/
|
||||
int ble_hci_trans_set_acl_free_cb(os_mempool_put_fn *cb, void *arg)
|
||||
{
|
||||
ble_hci_acl_pool.mpe_put_cb = cb;
|
||||
ble_hci_acl_pool.mpe_put_arg = arg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int ble_hci_trans_reset(void)
|
||||
{
|
||||
/* No work to do. All allocated buffers are owned by the host or
|
||||
* controller, and they will get freed by their owners.
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Allocates a buffer (mbuf) for ACL operation.
|
||||
*
|
||||
* @return The allocated buffer on success;
|
||||
* NULL on buffer exhaustion.
|
||||
*/
|
||||
static struct os_mbuf *ble_hci_trans_acl_buf_alloc(void)
|
||||
{
|
||||
struct os_mbuf *m;
|
||||
uint8_t usrhdr_len;
|
||||
|
||||
#if MYNEWT_VAL(BLE_DEVICE)
|
||||
usrhdr_len = sizeof(struct ble_mbuf_hdr);
|
||||
#elif MYNEWT_VAL(BLE_HS_FLOW_CTRL)
|
||||
usrhdr_len = BLE_MBUF_HS_HDR_LEN;
|
||||
#else
|
||||
usrhdr_len = 0;
|
||||
#endif
|
||||
|
||||
m = os_mbuf_get_pkthdr(&ble_hci_acl_mbuf_pool, usrhdr_len);
|
||||
return m;
|
||||
}
|
||||
|
||||
static void ble_hci_rx_acl(uint8_t *data, uint16_t len)
|
||||
{
|
||||
struct os_mbuf *m;
|
||||
int rc;
|
||||
int sr;
|
||||
if (len < BLE_HCI_DATA_HDR_SZ || len > MYNEWT_VAL(BLE_ACL_BUF_SIZE)) {
|
||||
return;
|
||||
}
|
||||
|
||||
m = ble_hci_trans_acl_buf_alloc();
|
||||
|
||||
if (!m) {
|
||||
ESP_LOGE(TAG, "%s failed to allocate ACL buffers; increase ACL_BUF_COUNT", __func__);
|
||||
return;
|
||||
}
|
||||
if ((rc = os_mbuf_append(m, data, len)) != 0) {
|
||||
ESP_LOGE(TAG, "%s failed to os_mbuf_append; rc = %d", __func__, rc);
|
||||
os_mbuf_free_chain(m);
|
||||
return;
|
||||
}
|
||||
OS_ENTER_CRITICAL(sr);
|
||||
if (ble_hci_rx_acl_hs_cb) {
|
||||
ble_hci_rx_acl_hs_cb(m, NULL);
|
||||
}
|
||||
OS_EXIT_CRITICAL(sr);
|
||||
}
|
||||
|
||||
static void ble_hci_transport_init(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/* Ensure this function only gets called by sysinit. */
|
||||
SYSINIT_ASSERT_ACTIVE();
|
||||
|
||||
rc = os_mempool_ext_init(&ble_hci_acl_pool,
|
||||
MYNEWT_VAL(BLE_ACL_BUF_COUNT),
|
||||
ACL_BLOCK_SIZE,
|
||||
ble_hci_acl_buf,
|
||||
"ble_hci_acl_pool");
|
||||
SYSINIT_PANIC_ASSERT(rc == 0);
|
||||
|
||||
rc = os_mbuf_pool_init(&ble_hci_acl_mbuf_pool,
|
||||
&ble_hci_acl_pool.mpe_mp,
|
||||
ACL_BLOCK_SIZE,
|
||||
MYNEWT_VAL(BLE_ACL_BUF_COUNT));
|
||||
SYSINIT_PANIC_ASSERT(rc == 0);
|
||||
|
||||
/*
|
||||
* Create memory pool of HCI command buffers. NOTE: we currently dont
|
||||
* allow this to be configured. The controller will only allow one
|
||||
* outstanding command. We decided to keep this a pool in case we allow
|
||||
* allow the controller to handle more than one outstanding command.
|
||||
*/
|
||||
rc = os_mempool_init(&ble_hci_cmd_pool,
|
||||
1,
|
||||
BLE_HCI_TRANS_CMD_SZ,
|
||||
ble_hci_cmd_buf,
|
||||
"ble_hci_cmd_pool");
|
||||
SYSINIT_PANIC_ASSERT(rc == 0);
|
||||
|
||||
rc = os_mempool_init(&ble_hci_evt_hi_pool,
|
||||
MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT),
|
||||
MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE),
|
||||
ble_hci_evt_hi_buf,
|
||||
"ble_hci_evt_hi_pool");
|
||||
SYSINIT_PANIC_ASSERT(rc == 0);
|
||||
|
||||
rc = os_mempool_init(&ble_hci_evt_lo_pool,
|
||||
MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT),
|
||||
MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE),
|
||||
ble_hci_evt_lo_buf,
|
||||
"ble_hci_evt_lo_pool");
|
||||
SYSINIT_PANIC_ASSERT(rc == 0);
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief: BT controller callback function, used to notify the upper layer that
|
||||
* controller is ready to receive command
|
||||
*/
|
||||
static void controller_rcv_pkt_ready(void)
|
||||
{
|
||||
if (vhci_send_sem) {
|
||||
xSemaphoreGive(vhci_send_sem);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* @brief: BT controller callback function, to transfer data packet to the host
|
||||
*/
|
||||
static int host_rcv_pkt(uint8_t *data, uint16_t len)
|
||||
{
|
||||
|
||||
if (data[0] == BLE_HCI_UART_H4_EVT) {
|
||||
uint8_t *evbuf;
|
||||
int totlen;
|
||||
int rc;
|
||||
|
||||
totlen = BLE_HCI_EVENT_HDR_LEN + data[2];
|
||||
assert(totlen <= UINT8_MAX + BLE_HCI_EVENT_HDR_LEN);
|
||||
|
||||
if (totlen > MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE)) {
|
||||
ESP_LOGE(TAG, "Received HCI data length at host (%d) exceeds maximum configured HCI event buffer size (%d).",
|
||||
totlen, MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE));
|
||||
ble_hs_sched_reset(BLE_HS_ECONTROLLER);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (data[1] == BLE_HCI_EVCODE_HW_ERROR) {
|
||||
assert(0);
|
||||
}
|
||||
|
||||
/* Allocate LE Advertising Report Event from lo pool only */
|
||||
if ((data[1] == BLE_HCI_EVCODE_LE_META) && (data[3] == BLE_HCI_LE_SUBEV_ADV_RPT)) {
|
||||
evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_LO);
|
||||
/* Skip advertising report if we're out of memory */
|
||||
if (!evbuf) {
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
evbuf = ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
|
||||
assert(evbuf != NULL);
|
||||
}
|
||||
|
||||
memcpy(evbuf, &data[1], totlen);
|
||||
|
||||
rc = ble_hci_trans_ll_evt_tx(evbuf);
|
||||
assert(rc == 0);
|
||||
} else if (data[0] == BLE_HCI_UART_H4_ACL) {
|
||||
ble_hci_rx_acl(data + 1, len - 1);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static const esp_vhci_host_callback_t vhci_host_cb = {
|
||||
.notify_host_send_available = controller_rcv_pkt_ready,
|
||||
.notify_host_recv = host_rcv_pkt,
|
||||
};
|
||||
|
||||
static void ble_buf_free(void)
|
||||
{
|
||||
os_msys_buf_free();
|
||||
|
||||
nimble_platform_mem_free(ble_hci_evt_hi_buf);
|
||||
ble_hci_evt_hi_buf = NULL;
|
||||
nimble_platform_mem_free(ble_hci_evt_lo_buf);
|
||||
ble_hci_evt_lo_buf = NULL;
|
||||
nimble_platform_mem_free(ble_hci_cmd_buf);
|
||||
ble_hci_cmd_buf = NULL;
|
||||
nimble_platform_mem_free(ble_hci_acl_buf);
|
||||
ble_hci_acl_buf = NULL;
|
||||
}
|
||||
|
||||
static esp_err_t ble_buf_alloc(void)
|
||||
{
|
||||
if (os_msys_buf_alloc()) {
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
|
||||
ble_hci_evt_hi_buf = (os_membuf_t *) nimble_platform_mem_calloc(1,
|
||||
(sizeof(os_membuf_t) * OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_HCI_EVT_HI_BUF_COUNT),
|
||||
MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE))));
|
||||
|
||||
ble_hci_evt_lo_buf = (os_membuf_t *) nimble_platform_mem_calloc(1,
|
||||
(sizeof(os_membuf_t) * OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_HCI_EVT_LO_BUF_COUNT),
|
||||
MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE))));
|
||||
|
||||
ble_hci_cmd_buf = (os_membuf_t *) nimble_platform_mem_calloc(1,
|
||||
(sizeof(os_membuf_t) * OS_MEMPOOL_SIZE(1, BLE_HCI_TRANS_CMD_SZ)));
|
||||
|
||||
ble_hci_acl_buf = (os_membuf_t *) nimble_platform_mem_calloc(1,
|
||||
(sizeof(os_membuf_t) * OS_MEMPOOL_SIZE(MYNEWT_VAL(BLE_ACL_BUF_COUNT),
|
||||
ACL_BLOCK_SIZE)));
|
||||
|
||||
if (!ble_hci_evt_hi_buf || !ble_hci_evt_lo_buf || !ble_hci_cmd_buf || !ble_hci_acl_buf) {
|
||||
ble_buf_free();
|
||||
return ESP_ERR_NO_MEM;
|
||||
}
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_nimble_hci_init(void)
|
||||
{
|
||||
esp_err_t ret;
|
||||
|
||||
ret = ble_buf_alloc();
|
||||
if (ret != ESP_OK) {
|
||||
goto err;
|
||||
}
|
||||
if ((ret = esp_vhci_host_register_callback(&vhci_host_cb)) != ESP_OK) {
|
||||
goto err;
|
||||
}
|
||||
|
||||
ble_hci_transport_init();
|
||||
|
||||
vhci_send_sem = xSemaphoreCreateBinary();
|
||||
if (vhci_send_sem == NULL) {
|
||||
ret = ESP_ERR_NO_MEM;
|
||||
goto err;
|
||||
}
|
||||
|
||||
xSemaphoreGive(vhci_send_sem);
|
||||
|
||||
return ret;
|
||||
err:
|
||||
ble_buf_free();
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
esp_err_t esp_nimble_hci_and_controller_init(void)
|
||||
{
|
||||
esp_err_t ret;
|
||||
|
||||
esp_bt_controller_mem_release(ESP_BT_MODE_CLASSIC_BT);
|
||||
|
||||
esp_bt_controller_config_t bt_cfg = BT_CONTROLLER_INIT_CONFIG_DEFAULT();
|
||||
|
||||
if ((ret = esp_bt_controller_init(&bt_cfg)) != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if ((ret = esp_bt_controller_enable(ESP_BT_MODE_BLE)) != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
return esp_nimble_hci_init();
|
||||
}
|
||||
|
||||
static esp_err_t ble_hci_transport_deinit(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret += os_mempool_clear(&ble_hci_evt_lo_pool);
|
||||
|
||||
ret += os_mempool_clear(&ble_hci_evt_hi_pool);
|
||||
|
||||
ret += os_mempool_clear(&ble_hci_cmd_pool);
|
||||
|
||||
ret += os_mempool_ext_clear(&ble_hci_acl_pool);
|
||||
|
||||
if (ret) {
|
||||
return ESP_FAIL;
|
||||
} else {
|
||||
return ESP_OK;
|
||||
}
|
||||
}
|
||||
|
||||
esp_err_t esp_nimble_hci_deinit(void)
|
||||
{
|
||||
if (vhci_send_sem) {
|
||||
/* Dummy take & give semaphore before deleting */
|
||||
xSemaphoreTake(vhci_send_sem, portMAX_DELAY);
|
||||
xSemaphoreGive(vhci_send_sem);
|
||||
vSemaphoreDelete(vhci_send_sem);
|
||||
vhci_send_sem = NULL;
|
||||
}
|
||||
esp_err_t ret = ble_hci_transport_deinit();
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ble_buf_free();
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
esp_err_t esp_nimble_hci_and_controller_deinit(void)
|
||||
{
|
||||
int ret;
|
||||
ret = esp_nimble_hci_deinit();
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = esp_bt_controller_disable();
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = esp_bt_controller_deinit();
|
||||
if (ret != ESP_OK) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
return ESP_OK;
|
||||
}
|
||||
|
||||
#endif
|
||||
1385
lib/NimBLE-Arduino/src/nimble/esp_port/port/include/esp_nimble_cfg.h
Normal file
1385
lib/NimBLE-Arduino/src/nimble/esp_port/port/include/esp_nimble_cfg.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifndef __ESP_NIMBLE_MEM_H__
|
||||
#define __ESP_NIMBLE_MEM_H__
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void *nimble_platform_mem_malloc(size_t size);
|
||||
void *nimble_platform_mem_calloc(size_t n, size_t size);
|
||||
void nimble_platform_mem_free(void *ptr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __ESP_NIMBLE_MEM_H__ */
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* SPDX-FileCopyrightText: 2015-2021 Espressif Systems (Shanghai) CO LTD
|
||||
*
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
#ifdef ESP_PLATFORM
|
||||
|
||||
#include "esp_attr.h"
|
||||
#include "esp_heap_caps.h"
|
||||
#include "nimconfig.h"
|
||||
#include "../include/esp_nimble_mem.h"
|
||||
|
||||
IRAM_ATTR void *nimble_platform_mem_malloc(size_t size)
|
||||
{
|
||||
#ifdef CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL
|
||||
return heap_caps_malloc(size, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
|
||||
#elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL
|
||||
return heap_caps_malloc(size, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT);
|
||||
#elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_IRAM_8BIT
|
||||
return heap_caps_malloc_prefer(size, 2, MALLOC_CAP_INTERNAL|MALLOC_CAP_IRAM_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
|
||||
#else
|
||||
return malloc(size);
|
||||
#endif
|
||||
}
|
||||
|
||||
IRAM_ATTR void *nimble_platform_mem_calloc(size_t n, size_t size)
|
||||
{
|
||||
#ifdef CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_INTERNAL
|
||||
return heap_caps_calloc(n, size, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
|
||||
#elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_EXTERNAL
|
||||
return heap_caps_calloc(n, size, MALLOC_CAP_SPIRAM|MALLOC_CAP_8BIT);
|
||||
#elif CONFIG_BT_NIMBLE_MEM_ALLOC_MODE_IRAM_8BIT
|
||||
return heap_caps_calloc_prefer(n, size, 2, MALLOC_CAP_INTERNAL|MALLOC_CAP_IRAM_8BIT, MALLOC_CAP_INTERNAL|MALLOC_CAP_8BIT);
|
||||
#else
|
||||
return calloc(n, size);
|
||||
#endif
|
||||
}
|
||||
|
||||
IRAM_ATTR void nimble_platform_mem_free(void *ptr)
|
||||
{
|
||||
heap_caps_free(ptr);
|
||||
}
|
||||
#endif
|
||||
15
lib/NimBLE-Arduino/src/nimble/ext/tinycrypt/AUTHORS
Normal file
15
lib/NimBLE-Arduino/src/nimble/ext/tinycrypt/AUTHORS
Normal file
@@ -0,0 +1,15 @@
|
||||
Architect:
|
||||
Rafael Misoczki <rafael.misoczki@intel.com>
|
||||
|
||||
Open Source Maintainer:
|
||||
Constanza Heath <constanza.m.heath@intel.com>
|
||||
Rafael Misoczki <rafael.misoczki@intel.com>
|
||||
|
||||
Contributors:
|
||||
Constanza Heath <constanza.m.heath@intel.com>
|
||||
Rafael Misoczki <rafael.misoczki@intel.com>
|
||||
Flavio Santes <flavio.santes@intel.com>
|
||||
Jarkko Sakkinen <jarkko.sakkinen@intel.com>
|
||||
Chris Morrison
|
||||
Marti Bolivar
|
||||
Colin Ian King
|
||||
61
lib/NimBLE-Arduino/src/nimble/ext/tinycrypt/LICENSE
Normal file
61
lib/NimBLE-Arduino/src/nimble/ext/tinycrypt/LICENSE
Normal file
@@ -0,0 +1,61 @@
|
||||
|
||||
================================================================================
|
||||
|
||||
TinyCrypt Cryptographic Library
|
||||
|
||||
================================================================================
|
||||
|
||||
Copyright (c) 2017, Intel Corporation. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
- Neither the name of the Intel Corporation nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
================================================================================
|
||||
Copyright (c) 2014, Kenneth MacKay
|
||||
All rights reserved.
|
||||
|
||||
https://github.com/kmackay/micro-ecc
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
* Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
* Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
================================================================================
|
||||
71
lib/NimBLE-Arduino/src/nimble/ext/tinycrypt/README
Normal file
71
lib/NimBLE-Arduino/src/nimble/ext/tinycrypt/README
Normal file
@@ -0,0 +1,71 @@
|
||||
|
||||
================================================================================
|
||||
|
||||
TinyCrypt Cryptographic Library
|
||||
|
||||
================================================================================
|
||||
|
||||
Copyright (c) 2017, Intel Corporation. All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
- Redistributions of source code must retain the above copyright notice, this
|
||||
list of conditions and the following disclaimer.
|
||||
|
||||
- Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
- Neither the name of the Intel Corporation nor the names of its contributors
|
||||
may be used to endorse or promote products derived from this software
|
||||
without specific prior written permission.
|
||||
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
|
||||
ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
================================================================================
|
||||
|
||||
Overview:
|
||||
|
||||
The TinyCrypt Library provides an implementation for constrained devices of a
|
||||
minimal set of standard cryptography primitives.
|
||||
|
||||
Please, ***SEE THE DOCUMENTATION*** folder for more information on the supported
|
||||
cryptographic primitives and the limitations of TinyCrypt library. For usage,
|
||||
security and technicalities, please see the corresponding header file of each
|
||||
cryptographic primitive.
|
||||
|
||||
================================================================================
|
||||
|
||||
Organization:
|
||||
|
||||
/lib: C source code of the cryptographic primitives.
|
||||
/lib/include/tinycrypt: C header files of the cryptographic primitives.
|
||||
/tests: Test vectors of the cryptographic primitives.
|
||||
/doc: Documentation of TinyCrypt.
|
||||
|
||||
================================================================================
|
||||
|
||||
Building:
|
||||
|
||||
1) In Makefile.conf set:
|
||||
- CFLAGS for compiler flags.
|
||||
- CC for compiler.
|
||||
- ENABLE_TESTS for enabling (true) or disabling (false) tests compilation.
|
||||
2) In lib/Makefile select the primitives required by your project.
|
||||
3) In tests/Makefile select the corresponding tests of the selected primitives.
|
||||
4) make
|
||||
5) run tests in tests/
|
||||
|
||||
================================================================================
|
||||
|
||||
1
lib/NimBLE-Arduino/src/nimble/ext/tinycrypt/VERSION
Normal file
1
lib/NimBLE-Arduino/src/nimble/ext/tinycrypt/VERSION
Normal file
@@ -0,0 +1 @@
|
||||
0.2.8
|
||||
@@ -0,0 +1,352 @@
|
||||
|
||||
TinyCrypt Cryptographic Library
|
||||
###############################
|
||||
Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
|
||||
Overview
|
||||
********
|
||||
The TinyCrypt Library provides an implementation for targeting constrained devices
|
||||
with a minimal set of standard cryptography primitives, as listed below. To better
|
||||
serve applications targeting constrained devices, TinyCrypt implementations differ
|
||||
from the standard specifications (see the Important Remarks section for some
|
||||
important differences). Certain cryptographic primitives depend on other
|
||||
primitives, as mentioned in the list below.
|
||||
|
||||
Aside from the Important Remarks section below, valuable information on the usage,
|
||||
security and technicalities of each cryptographic primitive are found in the
|
||||
corresponding header file.
|
||||
|
||||
* SHA-256:
|
||||
|
||||
* Type of primitive: Hash function.
|
||||
* Standard Specification: NIST FIPS PUB 180-4.
|
||||
* Requires: --
|
||||
|
||||
* HMAC-SHA256:
|
||||
|
||||
* Type of primitive: Message authentication code.
|
||||
* Standard Specification: RFC 2104.
|
||||
* Requires: SHA-256
|
||||
|
||||
* HMAC-PRNG:
|
||||
|
||||
* Type of primitive: Pseudo-random number generator (256-bit strength).
|
||||
* Standard Specification: NIST SP 800-90A.
|
||||
* Requires: SHA-256 and HMAC-SHA256.
|
||||
|
||||
* AES-128:
|
||||
|
||||
* Type of primitive: Block cipher.
|
||||
* Standard Specification: NIST FIPS PUB 197.
|
||||
* Requires: --
|
||||
|
||||
* AES-CBC mode:
|
||||
|
||||
* Type of primitive: Encryption mode of operation.
|
||||
* Standard Specification: NIST SP 800-38A.
|
||||
* Requires: AES-128.
|
||||
|
||||
* AES-CTR mode:
|
||||
|
||||
* Type of primitive: Encryption mode of operation.
|
||||
* Standard Specification: NIST SP 800-38A.
|
||||
* Requires: AES-128.
|
||||
|
||||
* AES-CMAC mode:
|
||||
|
||||
* Type of primitive: Message authentication code.
|
||||
* Standard Specification: NIST SP 800-38B.
|
||||
* Requires: AES-128.
|
||||
|
||||
* AES-CCM mode:
|
||||
|
||||
* Type of primitive: Authenticated encryption.
|
||||
* Standard Specification: NIST SP 800-38C.
|
||||
* Requires: AES-128.
|
||||
|
||||
* CTR-PRNG:
|
||||
|
||||
* Type of primitive: Pseudo-random number generator (128-bit strength).
|
||||
* Standard Specification: NIST SP 800-90A.
|
||||
* Requires: AES-128.
|
||||
|
||||
* ECC-DH:
|
||||
|
||||
* Type of primitive: Key exchange based on curve NIST p-256.
|
||||
* Standard Specification: RFC 6090.
|
||||
* Requires: ECC auxiliary functions (ecc.h/c).
|
||||
|
||||
* ECC-DSA:
|
||||
|
||||
* Type of primitive: Digital signature based on curve NIST p-256.
|
||||
* Standard Specification: RFC 6090.
|
||||
* Requires: ECC auxiliary functions (ecc.h/c).
|
||||
|
||||
Design Goals
|
||||
************
|
||||
|
||||
* Minimize the code size of each cryptographic primitive. This means minimize
|
||||
the size of a platform-independent implementation, as presented in TinyCrypt.
|
||||
Note that various applications may require further features, optimizations with
|
||||
respect to other metrics and countermeasures for particular threats. These
|
||||
peculiarities would increase the code size and thus are not considered here.
|
||||
|
||||
* Minimize the dependencies among the cryptographic primitives. This means
|
||||
that it is unnecessary to build and allocate object code for more primitives
|
||||
than the ones strictly required by the intended application. In other words,
|
||||
one can select and compile only the primitives required by the application.
|
||||
|
||||
|
||||
Important Remarks
|
||||
*****************
|
||||
|
||||
The cryptographic implementations in TinyCrypt library have some limitations.
|
||||
Some of these limitations are inherent to the cryptographic primitives
|
||||
themselves, while others are specific to TinyCrypt. These limitations were accepted
|
||||
in order to meet its design goals (in special, minimal code size) and to better
|
||||
serve applications targeting constrained devices in general. Some of these
|
||||
limitations are discussed in-depth below.
|
||||
|
||||
General Remarks
|
||||
***************
|
||||
|
||||
* TinyCrypt does **not** intend to be fully side-channel resistant. Due to the
|
||||
variety of side-channel attacks, many of them only relevant to certain
|
||||
platforms. In this sense, instead of penalizing all library users with
|
||||
side-channel countermeasures such as increasing the overall code size,
|
||||
TinyCrypt only implements certain generic timing-attack countermeasures.
|
||||
|
||||
Specific Remarks
|
||||
****************
|
||||
|
||||
* SHA-256:
|
||||
|
||||
* The number of bits_hashed in the state is not checked for overflow. Note
|
||||
however that this will only be a problem if you intend to hash more than
|
||||
2^64 bits, which is an extremely large window.
|
||||
|
||||
* HMAC:
|
||||
|
||||
* The HMAC verification process is assumed to be performed by the application.
|
||||
This compares the computed tag with some given tag.
|
||||
Note that conventional memory-comparison methods (such as memcmp function)
|
||||
might be vulnerable to timing attacks; thus be sure to use a constant-time
|
||||
memory comparison function (such as compare_constant_time
|
||||
function provided in lib/utils.c).
|
||||
|
||||
* The tc_hmac_final function, responsible for computing the message tag,
|
||||
cleans the state context before exiting. Thus, applications do not need to
|
||||
clean the TCHmacState_t ctx after calling tc_hmac_final. This should not
|
||||
be changed in future versions of the library as there are applications
|
||||
currently relying on this good-practice/feature of TinyCrypt.
|
||||
|
||||
* HMAC-PRNG:
|
||||
|
||||
* Before using HMAC-PRNG, you *must* find an entropy source to produce a seed.
|
||||
PRNGs only stretch the seed into a seemingly random output of arbitrary
|
||||
length. The security of the output is exactly equal to the
|
||||
unpredictability of the seed.
|
||||
|
||||
* NIST SP 800-90A requires three items as seed material in the initialization
|
||||
step: entropy seed, personalization and a nonce (which is not implemented).
|
||||
TinyCrypt requires the personalization byte array and automatically creates
|
||||
the entropy seed using a mandatory call to the re-seed function.
|
||||
|
||||
* AES-128:
|
||||
|
||||
* The current implementation does not support other key-lengths (such as 256
|
||||
bits). Note that if you need AES-256, it doesn't sound as though your
|
||||
application is running in a constrained environment. AES-256 requires keys
|
||||
twice the size as for AES-128, and the key schedule is 40% larger.
|
||||
|
||||
* CTR mode:
|
||||
|
||||
* The AES-CTR mode limits the size of a data message they encrypt to 2^32
|
||||
blocks. If you need to encrypt larger data sets, your application would
|
||||
need to replace the key after 2^32 block encryptions.
|
||||
|
||||
* CTR-PRNG:
|
||||
|
||||
* Before using CTR-PRNG, you *must* find an entropy source to produce a seed.
|
||||
PRNGs only stretch the seed into a seemingly random output of arbitrary
|
||||
length. The security of the output is exactly equal to the
|
||||
unpredictability of the seed.
|
||||
|
||||
* CBC mode:
|
||||
|
||||
* TinyCrypt CBC decryption assumes that the iv and the ciphertext are
|
||||
contiguous (as produced by TinyCrypt CBC encryption). This allows for a
|
||||
very efficient decryption algorithm that would not otherwise be possible.
|
||||
|
||||
* CMAC mode:
|
||||
|
||||
* AES128-CMAC mode of operation offers 64 bits of security against collision
|
||||
attacks. Note however that an external attacker cannot generate the tags
|
||||
him/herself without knowing the MAC key. In this sense, to attack the
|
||||
collision property of AES128-CMAC, an external attacker would need the
|
||||
cooperation of the legal user to produce an exponentially high number of
|
||||
tags (e.g. 2^64) to finally be able to look for collisions and benefit
|
||||
from them. As an extra precaution, the current implementation allows to at
|
||||
most 2^48 calls to tc_cmac_update function before re-calling tc_cmac_setup
|
||||
(allowing a new key to be set), as suggested in Appendix B of SP 800-38B.
|
||||
|
||||
* CCM mode:
|
||||
|
||||
* There are a few tradeoffs for the selection of the parameters of CCM mode.
|
||||
In special, there is a tradeoff between the maximum number of invocations
|
||||
of CCM under a given key and the maximum payload length for those
|
||||
invocations. Both things are related to the parameter 'q' of CCM mode. The
|
||||
maximum number of invocations of CCM under a given key is determined by
|
||||
the nonce size, which is: 15-q bytes. The maximum payload length for those
|
||||
invocations is defined as 2^(8q) bytes.
|
||||
|
||||
To achieve minimal code size, TinyCrypt CCM implementation fixes q = 2,
|
||||
which is a quite reasonable choice for constrained applications. The
|
||||
implications of this choice are:
|
||||
|
||||
The nonce size is: 13 bytes.
|
||||
|
||||
The maximum payload length is: 2^16 bytes = 65 KB.
|
||||
|
||||
The mac size parameter is an important parameter to estimate the security
|
||||
against collision attacks (that aim at finding different messages that
|
||||
produce the same authentication tag). TinyCrypt CCM implementation
|
||||
accepts any even integer between 4 and 16, as suggested in SP 800-38C.
|
||||
|
||||
* TinyCrypt CCM implementation accepts associated data of any length between
|
||||
0 and (2^16 - 2^8) = 65280 bytes.
|
||||
|
||||
* TinyCrypt CCM implementation accepts:
|
||||
|
||||
* Both non-empty payload and associated data (it encrypts and
|
||||
authenticates the payload and only authenticates the associated data);
|
||||
|
||||
* Non-empty payload and empty associated data (it encrypts and
|
||||
authenticates the payload);
|
||||
|
||||
* Non-empty associated data and empty payload (it degenerates to an
|
||||
authentication-only mode on the associated data).
|
||||
|
||||
* RFC-3610, which also specifies CCM, presents a few relevant security
|
||||
suggestions, such as: it is recommended for most applications to use a
|
||||
mac size greater than 8. Besides, it is emphasized that the usage of the
|
||||
same nonce for two different messages which are encrypted with the same
|
||||
key obviously destroys the security properties of CCM mode.
|
||||
|
||||
* ECC-DH and ECC-DSA:
|
||||
|
||||
* TinyCrypt ECC implementation is based on micro-ecc (see
|
||||
https://github.com/kmackay/micro-ecc). In the original micro-ecc
|
||||
documentation, there is an important remark about the way integers are
|
||||
represented:
|
||||
|
||||
"Integer representation: To reduce code size, all large integers are
|
||||
represented using little-endian words - so the least significant word is
|
||||
first. You can use the 'ecc_bytes2native()' and 'ecc_native2bytes()'
|
||||
functions to convert between the native integer representation and the
|
||||
standardized octet representation."
|
||||
|
||||
Note that the assumed bit layout is: {31, 30, ..., 0}, {63, 62, ..., 32},
|
||||
{95, 94, ..., 64}, {127, 126, ..., 96} for a very-long-integer (vli)
|
||||
consisting of 4 unsigned integers (as an example).
|
||||
|
||||
* A cryptographically-secure PRNG function must be set (using uECC_set_rng())
|
||||
before calling uECC_make_key() or uECC_sign().
|
||||
|
||||
Examples of Applications
|
||||
************************
|
||||
It is possible to do useful cryptography with only the given small set of
|
||||
primitives. With this list of primitives it becomes feasible to support a range
|
||||
of cryptography usages:
|
||||
|
||||
* Measurement of code, data structures, and other digital artifacts (SHA256);
|
||||
|
||||
* Generate commitments (SHA256);
|
||||
|
||||
* Construct keys (HMAC-SHA256);
|
||||
|
||||
* Extract entropy from strings containing some randomness (HMAC-SHA256);
|
||||
|
||||
* Construct random mappings (HMAC-SHA256);
|
||||
|
||||
* Construct nonces and challenges (HMAC-PRNG, CTR-PRNG);
|
||||
|
||||
* Authenticate using a shared secret (HMAC-SHA256);
|
||||
|
||||
* Create an authenticated, replay-protected session (HMAC-SHA256 + HMAC-PRNG);
|
||||
|
||||
* Authenticated encryption (AES-128 + AES-CCM);
|
||||
|
||||
* Key-exchange (EC-DH);
|
||||
|
||||
* Digital signature (EC-DSA);
|
||||
|
||||
Test Vectors
|
||||
************
|
||||
|
||||
The library provides a test program for each cryptographic primitive (see 'test'
|
||||
folder). Besides illustrating how to use the primitives, these tests evaluate
|
||||
the correctness of the implementations by checking the results against
|
||||
well-known publicly validated test vectors.
|
||||
|
||||
For the case of the HMAC-PRNG, due to the necessity of performing an extensive
|
||||
battery test to produce meaningful conclusions, we suggest the user to evaluate
|
||||
the unpredictability of the implementation by using the NIST Statistical Test
|
||||
Suite (see References).
|
||||
|
||||
For the case of the EC-DH and EC-DSA implementations, most of the test vectors
|
||||
were obtained from the site of the NIST Cryptographic Algorithm Validation
|
||||
Program (CAVP), see References.
|
||||
|
||||
References
|
||||
**********
|
||||
|
||||
* `NIST FIPS PUB 180-4 (SHA-256)`_
|
||||
|
||||
.. _NIST FIPS PUB 180-4 (SHA-256):
|
||||
http://csrc.nist.gov/publications/fips/fips180-4/fips-180-4.pdf
|
||||
|
||||
* `NIST FIPS PUB 197 (AES-128)`_
|
||||
|
||||
.. _NIST FIPS PUB 197 (AES-128):
|
||||
http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
|
||||
|
||||
* `NIST SP800-90A (HMAC-PRNG)`_
|
||||
|
||||
.. _NIST SP800-90A (HMAC-PRNG):
|
||||
http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf
|
||||
|
||||
* `NIST SP 800-38A (AES-CBC and AES-CTR)`_
|
||||
|
||||
.. _NIST SP 800-38A (AES-CBC and AES-CTR):
|
||||
http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf
|
||||
|
||||
* `NIST SP 800-38B (AES-CMAC)`_
|
||||
|
||||
.. _NIST SP 800-38B (AES-CMAC):
|
||||
http://csrc.nist.gov/publications/nistpubs/800-38B/SP_800-38B.pdf
|
||||
|
||||
* `NIST SP 800-38C (AES-CCM)`_
|
||||
|
||||
.. _NIST SP 800-38C (AES-CCM):
|
||||
http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf
|
||||
|
||||
* `NIST Statistical Test Suite (useful for testing HMAC-PRNG)`_
|
||||
|
||||
.. _NIST Statistical Test Suite (useful for testing HMAC-PRNG):
|
||||
http://csrc.nist.gov/groups/ST/toolkit/rng/documentation_software.html
|
||||
|
||||
* `NIST Cryptographic Algorithm Validation Program (CAVP) site`_
|
||||
|
||||
.. _NIST Cryptographic Algorithm Validation Program (CAVP) site:
|
||||
http://csrc.nist.gov/groups/STM/cavp/
|
||||
|
||||
* `RFC 2104 (HMAC-SHA256)`_
|
||||
|
||||
.. _RFC 2104 (HMAC-SHA256):
|
||||
https://www.ietf.org/rfc/rfc2104.txt
|
||||
|
||||
* `RFC 6090 (ECC-DH and ECC-DSA)`_
|
||||
|
||||
.. _RFC 6090 (ECC-DH and ECC-DSA):
|
||||
https://www.ietf.org/rfc/rfc6090.txt
|
||||
@@ -0,0 +1,130 @@
|
||||
/* aes.h - TinyCrypt interface to an AES-128 implementation */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief -- Interface to an AES-128 implementation.
|
||||
*
|
||||
* Overview: AES-128 is a NIST approved block cipher specified in
|
||||
* FIPS 197. Block ciphers are deterministic algorithms that
|
||||
* perform a transformation specified by a symmetric key in fixed-
|
||||
* length data sets, also called blocks.
|
||||
*
|
||||
* Security: AES-128 provides approximately 128 bits of security.
|
||||
*
|
||||
* Usage: 1) call tc_aes128_set_encrypt/decrypt_key to set the key.
|
||||
*
|
||||
* 2) call tc_aes_encrypt/decrypt to process the data.
|
||||
*/
|
||||
|
||||
#ifndef __TC_AES_H__
|
||||
#define __TC_AES_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define Nb (4) /* number of columns (32-bit words) comprising the state */
|
||||
#define Nk (4) /* number of 32-bit words comprising the key */
|
||||
#define Nr (10) /* number of rounds */
|
||||
#define TC_AES_BLOCK_SIZE (Nb*Nk)
|
||||
#define TC_AES_KEY_SIZE (Nb*Nk)
|
||||
|
||||
typedef struct tc_aes_key_sched_struct {
|
||||
unsigned int words[Nb*(Nr+1)];
|
||||
} *TCAesKeySched_t;
|
||||
|
||||
/**
|
||||
* @brief Set AES-128 encryption key
|
||||
* Uses key k to initialize s
|
||||
* @return returns TC_CRYPTO_SUCCESS (1)
|
||||
* returns TC_CRYPTO_FAIL (0) if: s == NULL or k == NULL
|
||||
* @note This implementation skips the additional steps required for keys
|
||||
* larger than 128 bits, and must not be used for AES-192 or
|
||||
* AES-256 key schedule -- see FIPS 197 for details
|
||||
* @param s IN/OUT -- initialized struct tc_aes_key_sched_struct
|
||||
* @param k IN -- points to the AES key
|
||||
*/
|
||||
int tc_aes128_set_encrypt_key(TCAesKeySched_t s, const uint8_t *k);
|
||||
|
||||
/**
|
||||
* @brief AES-128 Encryption procedure
|
||||
* Encrypts contents of in buffer into out buffer under key;
|
||||
* schedule s
|
||||
* @note Assumes s was initialized by aes_set_encrypt_key;
|
||||
* out and in point to 16 byte buffers
|
||||
* @return returns TC_CRYPTO_SUCCESS (1)
|
||||
* returns TC_CRYPTO_FAIL (0) if: out == NULL or in == NULL or s == NULL
|
||||
* @param out IN/OUT -- buffer to receive ciphertext block
|
||||
* @param in IN -- a plaintext block to encrypt
|
||||
* @param s IN -- initialized AES key schedule
|
||||
*/
|
||||
int tc_aes_encrypt(uint8_t *out, const uint8_t *in,
|
||||
const TCAesKeySched_t s);
|
||||
|
||||
/**
|
||||
* @brief Set the AES-128 decryption key
|
||||
* Uses key k to initialize s
|
||||
* @return returns TC_CRYPTO_SUCCESS (1)
|
||||
* returns TC_CRYPTO_FAIL (0) if: s == NULL or k == NULL
|
||||
* @note This is the implementation of the straightforward inverse cipher
|
||||
* using the cipher documented in FIPS-197 figure 12, not the
|
||||
* equivalent inverse cipher presented in Figure 15
|
||||
* @warning This routine skips the additional steps required for keys larger
|
||||
* than 128, and must not be used for AES-192 or AES-256 key
|
||||
* schedule -- see FIPS 197 for details
|
||||
* @param s IN/OUT -- initialized struct tc_aes_key_sched_struct
|
||||
* @param k IN -- points to the AES key
|
||||
*/
|
||||
int tc_aes128_set_decrypt_key(TCAesKeySched_t s, const uint8_t *k);
|
||||
|
||||
/**
|
||||
* @brief AES-128 Encryption procedure
|
||||
* Decrypts in buffer into out buffer under key schedule s
|
||||
* @return returns TC_CRYPTO_SUCCESS (1)
|
||||
* returns TC_CRYPTO_FAIL (0) if: out is NULL or in is NULL or s is NULL
|
||||
* @note Assumes s was initialized by aes_set_encrypt_key
|
||||
* out and in point to 16 byte buffers
|
||||
* @param out IN/OUT -- buffer to receive ciphertext block
|
||||
* @param in IN -- a plaintext block to encrypt
|
||||
* @param s IN -- initialized AES key schedule
|
||||
*/
|
||||
int tc_aes_decrypt(uint8_t *out, const uint8_t *in,
|
||||
const TCAesKeySched_t s);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __TC_AES_H__ */
|
||||
@@ -0,0 +1,151 @@
|
||||
/* cbc_mode.h - TinyCrypt interface to a CBC mode implementation */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Interface to a CBC mode implementation.
|
||||
*
|
||||
* Overview: CBC (for "cipher block chaining") mode is a NIST approved mode of
|
||||
* operation defined in SP 800-38a. It can be used with any block
|
||||
* cipher to provide confidentiality of strings whose lengths are
|
||||
* multiples of the block_size of the underlying block cipher.
|
||||
* TinyCrypt hard codes AES as the block cipher.
|
||||
*
|
||||
* Security: CBC mode provides data confidentiality given that the maximum
|
||||
* number q of blocks encrypted under a single key satisfies
|
||||
* q < 2^63, which is not a practical constraint (it is considered a
|
||||
* good practice to replace the encryption when q == 2^56). CBC mode
|
||||
* provides NO data integrity.
|
||||
*
|
||||
* CBC mode assumes that the IV value input into the
|
||||
* tc_cbc_mode_encrypt is randomly generated. The TinyCrypt library
|
||||
* provides HMAC-PRNG module, which generates suitable IVs. Other
|
||||
* methods for generating IVs are acceptable, provided that the
|
||||
* values of the IVs generated appear random to any adversary,
|
||||
* including someone with complete knowledge of the system design.
|
||||
*
|
||||
* The randomness property on which CBC mode's security depends is
|
||||
* the unpredictability of the IV. Since it is unpredictable, this
|
||||
* means in practice that CBC mode requires that the IV is stored
|
||||
* somehow with the ciphertext in order to recover the plaintext.
|
||||
*
|
||||
* TinyCrypt CBC encryption prepends the IV to the ciphertext,
|
||||
* because this affords a more efficient (few buffers) decryption.
|
||||
* Hence tc_cbc_mode_encrypt assumes the ciphertext buffer is always
|
||||
* 16 bytes larger than the plaintext buffer.
|
||||
*
|
||||
* Requires: AES-128
|
||||
*
|
||||
* Usage: 1) call tc_cbc_mode_encrypt to encrypt data.
|
||||
*
|
||||
* 2) call tc_cbc_mode_decrypt to decrypt data.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __TC_CBC_MODE_H__
|
||||
#define __TC_CBC_MODE_H__
|
||||
|
||||
#include "aes.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief CBC encryption procedure
|
||||
* CBC encrypts inlen bytes of the in buffer into the out buffer
|
||||
* using the encryption key schedule provided, prepends iv to out
|
||||
* @return returns TC_CRYPTO_SUCCESS (1)
|
||||
* returns TC_CRYPTO_FAIL (0) if:
|
||||
* out == NULL or
|
||||
* in == NULL or
|
||||
* ctr == NULL or
|
||||
* sched == NULL or
|
||||
* inlen == 0 or
|
||||
* (inlen % TC_AES_BLOCK_SIZE) != 0 or
|
||||
* (outlen % TC_AES_BLOCK_SIZE) != 0 or
|
||||
* outlen != inlen + TC_AES_BLOCK_SIZE
|
||||
* @note Assumes: - sched has been configured by aes_set_encrypt_key
|
||||
* - iv contains a 16 byte random string
|
||||
* - out buffer is large enough to hold the ciphertext + iv
|
||||
* - out buffer is a contiguous buffer
|
||||
* - in holds the plaintext and is a contiguous buffer
|
||||
* - inlen gives the number of bytes in the in buffer
|
||||
* @param out IN/OUT -- buffer to receive the ciphertext
|
||||
* @param outlen IN -- length of ciphertext buffer in bytes
|
||||
* @param in IN -- plaintext to encrypt
|
||||
* @param inlen IN -- length of plaintext buffer in bytes
|
||||
* @param iv IN -- the IV for the this encrypt/decrypt
|
||||
* @param sched IN -- AES key schedule for this encrypt
|
||||
*/
|
||||
int tc_cbc_mode_encrypt(uint8_t *out, unsigned int outlen, const uint8_t *in,
|
||||
unsigned int inlen, const uint8_t *iv,
|
||||
const TCAesKeySched_t sched);
|
||||
|
||||
/**
|
||||
* @brief CBC decryption procedure
|
||||
* CBC decrypts inlen bytes of the in buffer into the out buffer
|
||||
* using the provided encryption key schedule
|
||||
* @return returns TC_CRYPTO_SUCCESS (1)
|
||||
* returns TC_CRYPTO_FAIL (0) if:
|
||||
* out == NULL or
|
||||
* in == NULL or
|
||||
* sched == NULL or
|
||||
* inlen == 0 or
|
||||
* outlen == 0 or
|
||||
* (inlen % TC_AES_BLOCK_SIZE) != 0 or
|
||||
* (outlen % TC_AES_BLOCK_SIZE) != 0 or
|
||||
* outlen != inlen + TC_AES_BLOCK_SIZE
|
||||
* @note Assumes:- in == iv + ciphertext, i.e. the iv and the ciphertext are
|
||||
* contiguous. This allows for a very efficient decryption
|
||||
* algorithm that would not otherwise be possible
|
||||
* - sched was configured by aes_set_decrypt_key
|
||||
* - out buffer is large enough to hold the decrypted plaintext
|
||||
* and is a contiguous buffer
|
||||
* - inlen gives the number of bytes in the in buffer
|
||||
* @param out IN/OUT -- buffer to receive decrypted data
|
||||
* @param outlen IN -- length of plaintext buffer in bytes
|
||||
* @param in IN -- ciphertext to decrypt, including IV
|
||||
* @param inlen IN -- length of ciphertext buffer in bytes
|
||||
* @param iv IN -- the IV for the this encrypt/decrypt
|
||||
* @param sched IN -- AES key schedule for this decrypt
|
||||
*
|
||||
*/
|
||||
int tc_cbc_mode_decrypt(uint8_t *out, unsigned int outlen, const uint8_t *in,
|
||||
unsigned int inlen, const uint8_t *iv,
|
||||
const TCAesKeySched_t sched);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __TC_CBC_MODE_H__ */
|
||||
@@ -0,0 +1,211 @@
|
||||
/* ccm_mode.h - TinyCrypt interface to a CCM mode implementation */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Interface to a CCM mode implementation.
|
||||
*
|
||||
* Overview: CCM (for "Counter with CBC-MAC") mode is a NIST approved mode of
|
||||
* operation defined in SP 800-38C.
|
||||
*
|
||||
* TinyCrypt CCM implementation accepts:
|
||||
*
|
||||
* 1) Both non-empty payload and associated data (it encrypts and
|
||||
* authenticates the payload and also authenticates the associated
|
||||
* data);
|
||||
* 2) Non-empty payload and empty associated data (it encrypts and
|
||||
* authenticates the payload);
|
||||
* 3) Non-empty associated data and empty payload (it degenerates to
|
||||
* an authentication mode on the associated data).
|
||||
*
|
||||
* TinyCrypt CCM implementation accepts associated data of any length
|
||||
* between 0 and (2^16 - 2^8) bytes.
|
||||
*
|
||||
* Security: The mac length parameter is an important parameter to estimate the
|
||||
* security against collision attacks (that aim at finding different
|
||||
* messages that produce the same authentication tag). TinyCrypt CCM
|
||||
* implementation accepts any even integer between 4 and 16, as
|
||||
* suggested in SP 800-38C.
|
||||
*
|
||||
* RFC-3610, which also specifies CCM, presents a few relevant
|
||||
* security suggestions, such as: it is recommended for most
|
||||
* applications to use a mac length greater than 8. Besides, the
|
||||
* usage of the same nonce for two different messages which are
|
||||
* encrypted with the same key destroys the security of CCM mode.
|
||||
*
|
||||
* Requires: AES-128
|
||||
*
|
||||
* Usage: 1) call tc_ccm_config to configure.
|
||||
*
|
||||
* 2) call tc_ccm_mode_encrypt to encrypt data and generate tag.
|
||||
*
|
||||
* 3) call tc_ccm_mode_decrypt to decrypt data and verify tag.
|
||||
*/
|
||||
|
||||
#ifndef __TC_CCM_MODE_H__
|
||||
#define __TC_CCM_MODE_H__
|
||||
|
||||
#include "aes.h"
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* max additional authenticated size in bytes: 2^16 - 2^8 = 65280 */
|
||||
#define TC_CCM_AAD_MAX_BYTES 0xff00
|
||||
|
||||
/* max message size in bytes: 2^(8L) = 2^16 = 65536 */
|
||||
#define TC_CCM_PAYLOAD_MAX_BYTES 0x10000
|
||||
|
||||
/* struct tc_ccm_mode_struct represents the state of a CCM computation */
|
||||
typedef struct tc_ccm_mode_struct {
|
||||
TCAesKeySched_t sched; /* AES key schedule */
|
||||
uint8_t *nonce; /* nonce required by CCM */
|
||||
unsigned int mlen; /* mac length in bytes (parameter t in SP-800 38C) */
|
||||
} *TCCcmMode_t;
|
||||
|
||||
/**
|
||||
* @brief CCM configuration procedure
|
||||
* @return returns TC_CRYPTO_SUCCESS (1)
|
||||
* returns TC_CRYPTO_FAIL (0) if:
|
||||
* c == NULL or
|
||||
* sched == NULL or
|
||||
* nonce == NULL or
|
||||
* mlen != {4, 6, 8, 10, 12, 16}
|
||||
* @param c -- CCM state
|
||||
* @param sched IN -- AES key schedule
|
||||
* @param nonce IN - nonce
|
||||
* @param nlen -- nonce length in bytes
|
||||
* @param mlen -- mac length in bytes (parameter t in SP-800 38C)
|
||||
*/
|
||||
int tc_ccm_config(TCCcmMode_t c, TCAesKeySched_t sched, uint8_t *nonce,
|
||||
unsigned int nlen, unsigned int mlen);
|
||||
|
||||
/**
|
||||
* @brief CCM tag generation and encryption procedure
|
||||
* @return returns TC_CRYPTO_SUCCESS (1)
|
||||
* returns TC_CRYPTO_FAIL (0) if:
|
||||
* out == NULL or
|
||||
* c == NULL or
|
||||
* ((plen > 0) and (payload == NULL)) or
|
||||
* ((alen > 0) and (associated_data == NULL)) or
|
||||
* (alen >= TC_CCM_AAD_MAX_BYTES) or
|
||||
* (plen >= TC_CCM_PAYLOAD_MAX_BYTES) or
|
||||
* (olen < plen + maclength)
|
||||
*
|
||||
* @param out OUT -- encrypted data
|
||||
* @param olen IN -- output length in bytes
|
||||
* @param associated_data IN -- associated data
|
||||
* @param alen IN -- associated data length in bytes
|
||||
* @param payload IN -- payload
|
||||
* @param plen IN -- payload length in bytes
|
||||
* @param c IN -- CCM state
|
||||
*
|
||||
* @note: out buffer should be at least (plen + c->mlen) bytes long.
|
||||
*
|
||||
* @note: The sequence b for encryption is formatted as follows:
|
||||
* b = [FLAGS | nonce | counter ], where:
|
||||
* FLAGS is 1 byte long
|
||||
* nonce is 13 bytes long
|
||||
* counter is 2 bytes long
|
||||
* The byte FLAGS is composed by the following 8 bits:
|
||||
* 0-2 bits: used to represent the value of q-1
|
||||
* 3-7 btis: always 0's
|
||||
*
|
||||
* @note: The sequence b for authentication is formatted as follows:
|
||||
* b = [FLAGS | nonce | length(mac length)], where:
|
||||
* FLAGS is 1 byte long
|
||||
* nonce is 13 bytes long
|
||||
* length(mac length) is 2 bytes long
|
||||
* The byte FLAGS is composed by the following 8 bits:
|
||||
* 0-2 bits: used to represent the value of q-1
|
||||
* 3-5 bits: mac length (encoded as: (mlen-2)/2)
|
||||
* 6: Adata (0 if alen == 0, and 1 otherwise)
|
||||
* 7: always 0
|
||||
*/
|
||||
int tc_ccm_generation_encryption(uint8_t *out, unsigned int olen,
|
||||
const uint8_t *associated_data,
|
||||
unsigned int alen, const uint8_t *payload,
|
||||
unsigned int plen, TCCcmMode_t c);
|
||||
|
||||
/**
|
||||
* @brief CCM decryption and tag verification procedure
|
||||
* @return returns TC_CRYPTO_SUCCESS (1)
|
||||
* returns TC_CRYPTO_FAIL (0) if:
|
||||
* out == NULL or
|
||||
* c == NULL or
|
||||
* ((plen > 0) and (payload == NULL)) or
|
||||
* ((alen > 0) and (associated_data == NULL)) or
|
||||
* (alen >= TC_CCM_AAD_MAX_BYTES) or
|
||||
* (plen >= TC_CCM_PAYLOAD_MAX_BYTES) or
|
||||
* (olen < plen - c->mlen)
|
||||
*
|
||||
* @param out OUT -- decrypted data
|
||||
* @param associated_data IN -- associated data
|
||||
* @param alen IN -- associated data length in bytes
|
||||
* @param payload IN -- payload
|
||||
* @param plen IN -- payload length in bytes
|
||||
* @param c IN -- CCM state
|
||||
*
|
||||
* @note: out buffer should be at least (plen - c->mlen) bytes long.
|
||||
*
|
||||
* @note: The sequence b for encryption is formatted as follows:
|
||||
* b = [FLAGS | nonce | counter ], where:
|
||||
* FLAGS is 1 byte long
|
||||
* nonce is 13 bytes long
|
||||
* counter is 2 bytes long
|
||||
* The byte FLAGS is composed by the following 8 bits:
|
||||
* 0-2 bits: used to represent the value of q-1
|
||||
* 3-7 btis: always 0's
|
||||
*
|
||||
* @note: The sequence b for authentication is formatted as follows:
|
||||
* b = [FLAGS | nonce | length(mac length)], where:
|
||||
* FLAGS is 1 byte long
|
||||
* nonce is 13 bytes long
|
||||
* length(mac length) is 2 bytes long
|
||||
* The byte FLAGS is composed by the following 8 bits:
|
||||
* 0-2 bits: used to represent the value of q-1
|
||||
* 3-5 bits: mac length (encoded as: (mlen-2)/2)
|
||||
* 6: Adata (0 if alen == 0, and 1 otherwise)
|
||||
* 7: always 0
|
||||
*/
|
||||
int tc_ccm_decryption_verification(uint8_t *out, unsigned int olen,
|
||||
const uint8_t *associated_data,
|
||||
unsigned int alen, const uint8_t *payload, unsigned int plen,
|
||||
TCCcmMode_t c);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __TC_CCM_MODE_H__ */
|
||||
@@ -0,0 +1,194 @@
|
||||
/* cmac_mode.h -- interface to a CMAC implementation */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Interface to a CMAC implementation.
|
||||
*
|
||||
* Overview: CMAC is defined NIST in SP 800-38B, and is the standard algorithm
|
||||
* for computing a MAC using a block cipher. It can compute the MAC
|
||||
* for a byte string of any length. It is distinguished from CBC-MAC
|
||||
* in the processing of the final message block; CMAC uses a
|
||||
* different technique to compute the final message block is full
|
||||
* size or only partial, while CBC-MAC uses the same technique for
|
||||
* both. This difference permits CMAC to be applied to variable
|
||||
* length messages, while all messages authenticated by CBC-MAC must
|
||||
* be the same length.
|
||||
*
|
||||
* Security: AES128-CMAC mode of operation offers 64 bits of security against
|
||||
* collision attacks. Note however that an external attacker cannot
|
||||
* generate the tags him/herself without knowing the MAC key. In this
|
||||
* sense, to attack the collision property of AES128-CMAC, an
|
||||
* external attacker would need the cooperation of the legal user to
|
||||
* produce an exponentially high number of tags (e.g. 2^64) to
|
||||
* finally be able to look for collisions and benefit from them. As
|
||||
* an extra precaution, the current implementation allows to at most
|
||||
* 2^48 calls to the tc_cmac_update function before re-calling
|
||||
* tc_cmac_setup (allowing a new key to be set), as suggested in
|
||||
* Appendix B of SP 800-38B.
|
||||
*
|
||||
* Requires: AES-128
|
||||
*
|
||||
* Usage: This implementation provides a "scatter-gather" interface, so that
|
||||
* the CMAC value can be computed incrementally over a message
|
||||
* scattered in different segments throughout memory. Experience shows
|
||||
* this style of interface tends to minimize the burden of programming
|
||||
* correctly. Like all symmetric key operations, it is session
|
||||
* oriented.
|
||||
*
|
||||
* To begin a CMAC session, use tc_cmac_setup to initialize a struct
|
||||
* tc_cmac_struct with encryption key and buffer. Our implementation
|
||||
* always assume that the AES key to be the same size as the block
|
||||
* cipher block size. Once setup, this data structure can be used for
|
||||
* many CMAC computations.
|
||||
*
|
||||
* Once the state has been setup with a key, computing the CMAC of
|
||||
* some data requires three steps:
|
||||
*
|
||||
* (1) first use tc_cmac_init to initialize a new CMAC computation.
|
||||
* (2) next mix all of the data into the CMAC computation state using
|
||||
* tc_cmac_update. If all of the data resides in a single data
|
||||
* segment then only one tc_cmac_update call is needed; if data
|
||||
* is scattered throughout memory in n data segments, then n calls
|
||||
* will be needed. CMAC IS ORDER SENSITIVE, to be able to detect
|
||||
* attacks that swap bytes, so the order in which data is mixed
|
||||
* into the state is critical!
|
||||
* (3) Once all of the data for a message has been mixed, use
|
||||
* tc_cmac_final to compute the CMAC tag value.
|
||||
*
|
||||
* Steps (1)-(3) can be repeated as many times as you want to CMAC
|
||||
* multiple messages. A practical limit is 2^48 1K messages before you
|
||||
* have to change the key.
|
||||
*
|
||||
* Once you are done computing CMAC with a key, it is a good idea to
|
||||
* destroy the state so an attacker cannot recover the key; use
|
||||
* tc_cmac_erase to accomplish this.
|
||||
*/
|
||||
|
||||
#ifndef __TC_CMAC_MODE_H__
|
||||
#define __TC_CMAC_MODE_H__
|
||||
|
||||
#include "aes.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* padding for last message block */
|
||||
#define TC_CMAC_PADDING 0x80
|
||||
|
||||
/* struct tc_cmac_struct represents the state of a CMAC computation */
|
||||
typedef struct tc_cmac_struct {
|
||||
/* initialization vector */
|
||||
uint8_t iv[TC_AES_BLOCK_SIZE];
|
||||
/* used if message length is a multiple of block_size bytes */
|
||||
uint8_t K1[TC_AES_BLOCK_SIZE];
|
||||
/* used if message length isn't a multiple block_size bytes */
|
||||
uint8_t K2[TC_AES_BLOCK_SIZE];
|
||||
/* where to put bytes that didn't fill a block */
|
||||
uint8_t leftover[TC_AES_BLOCK_SIZE];
|
||||
/* identifies the encryption key */
|
||||
unsigned int keyid;
|
||||
/* next available leftover location */
|
||||
unsigned int leftover_offset;
|
||||
/* AES key schedule */
|
||||
TCAesKeySched_t sched;
|
||||
/* calls to tc_cmac_update left before re-key */
|
||||
uint64_t countdown;
|
||||
} *TCCmacState_t;
|
||||
|
||||
/**
|
||||
* @brief Configures the CMAC state to use the given AES key
|
||||
* @return returns TC_CRYPTO_SUCCESS (1) after having configured the CMAC state
|
||||
* returns TC_CRYPTO_FAIL (0) if:
|
||||
* s == NULL or
|
||||
* key == NULL
|
||||
*
|
||||
* @param s IN/OUT -- the state to set up
|
||||
* @param key IN -- the key to use
|
||||
* @param sched IN -- AES key schedule
|
||||
*/
|
||||
int tc_cmac_setup(TCCmacState_t s, const uint8_t *key,
|
||||
TCAesKeySched_t sched);
|
||||
|
||||
/**
|
||||
* @brief Erases the CMAC state
|
||||
* @return returns TC_CRYPTO_SUCCESS (1) after having configured the CMAC state
|
||||
* returns TC_CRYPTO_FAIL (0) if:
|
||||
* s == NULL
|
||||
*
|
||||
* @param s IN/OUT -- the state to erase
|
||||
*/
|
||||
int tc_cmac_erase(TCCmacState_t s);
|
||||
|
||||
/**
|
||||
* @brief Initializes a new CMAC computation
|
||||
* @return returns TC_CRYPTO_SUCCESS (1) after having initialized the CMAC state
|
||||
* returns TC_CRYPTO_FAIL (0) if:
|
||||
* s == NULL
|
||||
*
|
||||
* @param s IN/OUT -- the state to initialize
|
||||
*/
|
||||
int tc_cmac_init(TCCmacState_t s);
|
||||
|
||||
/**
|
||||
* @brief Incrementally computes CMAC over the next data segment
|
||||
* @return returns TC_CRYPTO_SUCCESS (1) after successfully updating the CMAC state
|
||||
* returns TC_CRYPTO_FAIL (0) if:
|
||||
* s == NULL or
|
||||
* if data == NULL when dlen > 0
|
||||
*
|
||||
* @param s IN/OUT -- the CMAC state
|
||||
* @param data IN -- the next data segment to MAC
|
||||
* @param dlen IN -- the length of data in bytes
|
||||
*/
|
||||
int tc_cmac_update(TCCmacState_t s, const uint8_t *data, size_t dlen);
|
||||
|
||||
/**
|
||||
* @brief Generates the tag from the CMAC state
|
||||
* @return returns TC_CRYPTO_SUCCESS (1) after successfully generating the tag
|
||||
* returns TC_CRYPTO_FAIL (0) if:
|
||||
* tag == NULL or
|
||||
* s == NULL
|
||||
*
|
||||
* @param tag OUT -- the CMAC tag
|
||||
* @param s IN -- CMAC state
|
||||
*/
|
||||
int tc_cmac_final(uint8_t *tag, TCCmacState_t s);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __TC_CMAC_MODE_H__ */
|
||||
@@ -0,0 +1,61 @@
|
||||
/* constants.h - TinyCrypt interface to constants */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief -- Interface to constants.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __TC_CONSTANTS_H__
|
||||
#define __TC_CONSTANTS_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifndef NULL
|
||||
#define NULL ((void *)0)
|
||||
#endif
|
||||
|
||||
#define TC_CRYPTO_SUCCESS 1
|
||||
#define TC_CRYPTO_FAIL 0
|
||||
|
||||
#define TC_ZERO_BYTE 0x00
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __TC_CONSTANTS_H__ */
|
||||
@@ -0,0 +1,108 @@
|
||||
/* ctr_mode.h - TinyCrypt interface to CTR mode */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Interface to CTR mode.
|
||||
*
|
||||
* Overview: CTR (pronounced "counter") mode is a NIST approved mode of
|
||||
* operation defined in SP 800-38a. It can be used with any
|
||||
* block cipher to provide confidentiality of strings of any
|
||||
* length. TinyCrypt hard codes AES128 as the block cipher.
|
||||
*
|
||||
* Security: CTR mode achieves confidentiality only if the counter value is
|
||||
* never reused with a same encryption key. If the counter is
|
||||
* repeated, than an adversary might be able to defeat the scheme.
|
||||
*
|
||||
* A usual method to ensure different counter values refers to
|
||||
* initialize the counter in a given value (0, for example) and
|
||||
* increases it every time a new block is enciphered. This naturally
|
||||
* leaves to a limitation on the number q of blocks that can be
|
||||
* enciphered using a same key: q < 2^(counter size).
|
||||
*
|
||||
* TinyCrypt uses a counter of 32 bits. This means that after 2^32
|
||||
* block encryptions, the counter will be reused (thus losing CBC
|
||||
* security). 2^32 block encryptions should be enough for most of
|
||||
* applications targeting constrained devices. Applications intended
|
||||
* to encrypt a larger number of blocks must replace the key after
|
||||
* 2^32 block encryptions.
|
||||
*
|
||||
* CTR mode provides NO data integrity.
|
||||
*
|
||||
* Requires: AES-128
|
||||
*
|
||||
* Usage: 1) call tc_ctr_mode to process the data to encrypt/decrypt.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __TC_CTR_MODE_H__
|
||||
#define __TC_CTR_MODE_H__
|
||||
|
||||
#include "aes.h"
|
||||
#include "constants.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief CTR mode encryption/decryption procedure.
|
||||
* CTR mode encrypts (or decrypts) inlen bytes from in buffer into out buffer
|
||||
* @return returns TC_CRYPTO_SUCCESS (1)
|
||||
* returns TC_CRYPTO_FAIL (0) if:
|
||||
* out == NULL or
|
||||
* in == NULL or
|
||||
* ctr == NULL or
|
||||
* sched == NULL or
|
||||
* inlen == 0 or
|
||||
* outlen == 0 or
|
||||
* inlen != outlen
|
||||
* @note Assumes:- The current value in ctr has NOT been used with sched
|
||||
* - out points to inlen bytes
|
||||
* - in points to inlen bytes
|
||||
* - ctr is an integer counter in littleEndian format
|
||||
* - sched was initialized by aes_set_encrypt_key
|
||||
* @param out OUT -- produced ciphertext (plaintext)
|
||||
* @param outlen IN -- length of ciphertext buffer in bytes
|
||||
* @param in IN -- data to encrypt (or decrypt)
|
||||
* @param inlen IN -- length of input data in bytes
|
||||
* @param ctr IN/OUT -- the current counter value
|
||||
* @param sched IN -- an initialized AES key schedule
|
||||
*/
|
||||
int tc_ctr_mode(uint8_t *out, unsigned int outlen, const uint8_t *in,
|
||||
unsigned int inlen, uint8_t *ctr, const TCAesKeySched_t sched);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __TC_CTR_MODE_H__ */
|
||||
@@ -0,0 +1,166 @@
|
||||
/* ctr_prng.h - TinyCrypt interface to a CTR-PRNG implementation */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2016, Chris Morrison
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Interface to a CTR-PRNG implementation.
|
||||
*
|
||||
* Overview: A pseudo-random number generator (PRNG) generates a sequence
|
||||
* of numbers that have a distribution close to the one expected
|
||||
* for a sequence of truly random numbers. The NIST Special
|
||||
* Publication 800-90A specifies several mechanisms to generate
|
||||
* sequences of pseudo random numbers, including the CTR-PRNG one
|
||||
* which is based on AES. TinyCrypt implements CTR-PRNG with
|
||||
* AES-128.
|
||||
*
|
||||
* Security: A cryptographically secure PRNG depends on the existence of an
|
||||
* entropy source to provide a truly random seed as well as the
|
||||
* security of the primitives used as the building blocks (AES-128
|
||||
* in this instance).
|
||||
*
|
||||
* Requires: - AES-128
|
||||
*
|
||||
* Usage: 1) call tc_ctr_prng_init to seed the prng context
|
||||
*
|
||||
* 2) call tc_ctr_prng_reseed to mix in additional entropy into
|
||||
* the prng context
|
||||
*
|
||||
* 3) call tc_ctr_prng_generate to output the pseudo-random data
|
||||
*
|
||||
* 4) call tc_ctr_prng_uninstantiate to zero out the prng context
|
||||
*/
|
||||
|
||||
#ifndef __TC_CTR_PRNG_H__
|
||||
#define __TC_CTR_PRNG_H__
|
||||
|
||||
#include "aes.h"
|
||||
|
||||
#define TC_CTR_PRNG_RESEED_REQ -1
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct {
|
||||
/* updated each time another BLOCKLEN_BYTES bytes are produced */
|
||||
uint8_t V[TC_AES_BLOCK_SIZE];
|
||||
|
||||
/* updated whenever the PRNG is reseeded */
|
||||
struct tc_aes_key_sched_struct key;
|
||||
|
||||
/* number of requests since initialization/reseeding */
|
||||
uint64_t reseedCount;
|
||||
} TCCtrPrng_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief CTR-PRNG initialization procedure
|
||||
* Initializes prng context with entropy and personalization string (if any)
|
||||
* @return returns TC_CRYPTO_SUCCESS (1)
|
||||
* returns TC_CRYPTO_FAIL (0) if:
|
||||
* ctx == NULL,
|
||||
* entropy == NULL,
|
||||
* entropyLen < (TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE)
|
||||
* @note Only the first (TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE) bytes of
|
||||
* both the entropy and personalization inputs are used -
|
||||
* supplying additional bytes has no effect.
|
||||
* @param ctx IN/OUT -- the PRNG context to initialize
|
||||
* @param entropy IN -- entropy used to seed the PRNG
|
||||
* @param entropyLen IN -- entropy length in bytes
|
||||
* @param personalization IN -- personalization string used to seed the PRNG
|
||||
* (may be null)
|
||||
* @param plen IN -- personalization length in bytes
|
||||
*
|
||||
*/
|
||||
int tc_ctr_prng_init(TCCtrPrng_t * const ctx,
|
||||
uint8_t const * const entropy,
|
||||
unsigned int entropyLen,
|
||||
uint8_t const * const personalization,
|
||||
unsigned int pLen);
|
||||
|
||||
/**
|
||||
* @brief CTR-PRNG reseed procedure
|
||||
* Mixes entropy and additional_input into the prng context
|
||||
* @return returns TC_CRYPTO_SUCCESS (1)
|
||||
* returns TC_CRYPTO_FAIL (0) if:
|
||||
* ctx == NULL,
|
||||
* entropy == NULL,
|
||||
* entropylen < (TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE)
|
||||
* @note It is better to reseed an existing prng context rather than
|
||||
* re-initialise, so that any existing entropy in the context is
|
||||
* presereved. This offers some protection against undetected failures
|
||||
* of the entropy source.
|
||||
* @note Assumes tc_ctr_prng_init has been called for ctx
|
||||
* @param ctx IN/OUT -- the PRNG state
|
||||
* @param entropy IN -- entropy to mix into the prng
|
||||
* @param entropylen IN -- length of entropy in bytes
|
||||
* @param additional_input IN -- additional input to the prng (may be null)
|
||||
* @param additionallen IN -- additional input length in bytes
|
||||
*/
|
||||
int tc_ctr_prng_reseed(TCCtrPrng_t * const ctx,
|
||||
uint8_t const * const entropy,
|
||||
unsigned int entropyLen,
|
||||
uint8_t const * const additional_input,
|
||||
unsigned int additionallen);
|
||||
|
||||
/**
|
||||
* @brief CTR-PRNG generate procedure
|
||||
* Generates outlen pseudo-random bytes into out buffer, updates prng
|
||||
* @return returns TC_CRYPTO_SUCCESS (1)
|
||||
* returns TC_CTR_PRNG_RESEED_REQ (-1) if a reseed is needed
|
||||
* returns TC_CRYPTO_FAIL (0) if:
|
||||
* ctx == NULL,
|
||||
* out == NULL,
|
||||
* outlen >= 2^16
|
||||
* @note Assumes tc_ctr_prng_init has been called for ctx
|
||||
* @param ctx IN/OUT -- the PRNG context
|
||||
* @param additional_input IN -- additional input to the prng (may be null)
|
||||
* @param additionallen IN -- additional input length in bytes
|
||||
* @param out IN/OUT -- buffer to receive output
|
||||
* @param outlen IN -- size of out buffer in bytes
|
||||
*/
|
||||
int tc_ctr_prng_generate(TCCtrPrng_t * const ctx,
|
||||
uint8_t const * const additional_input,
|
||||
unsigned int additionallen,
|
||||
uint8_t * const out,
|
||||
unsigned int outlen);
|
||||
|
||||
/**
|
||||
* @brief CTR-PRNG uninstantiate procedure
|
||||
* Zeroes the internal state of the supplied prng context
|
||||
* @return none
|
||||
* @param ctx IN/OUT -- the PRNG context
|
||||
*/
|
||||
void tc_ctr_prng_uninstantiate(TCCtrPrng_t * const ctx);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __TC_CTR_PRNG_H__ */
|
||||
@@ -0,0 +1,545 @@
|
||||
/* ecc.h - TinyCrypt interface to common ECC functions */
|
||||
|
||||
/* Copyright (c) 2014, Kenneth MacKay
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief -- Interface to common ECC functions.
|
||||
*
|
||||
* Overview: This software is an implementation of common functions
|
||||
* necessary to elliptic curve cryptography. This implementation uses
|
||||
* curve NIST p-256.
|
||||
*
|
||||
* Security: The curve NIST p-256 provides approximately 128 bits of security.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __TC_UECC_H__
|
||||
#define __TC_UECC_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Word size (4 bytes considering 32-bits architectures) */
|
||||
#define uECC_WORD_SIZE 4
|
||||
|
||||
/* setting max number of calls to prng: */
|
||||
#ifndef uECC_RNG_MAX_TRIES
|
||||
#define uECC_RNG_MAX_TRIES 64
|
||||
#endif
|
||||
|
||||
/* defining data types to store word and bit counts: */
|
||||
typedef int8_t wordcount_t;
|
||||
typedef int16_t bitcount_t;
|
||||
/* defining data type for comparison result: */
|
||||
typedef int8_t cmpresult_t;
|
||||
/* defining data type to store ECC coordinate/point in 32bits words: */
|
||||
typedef unsigned int uECC_word_t;
|
||||
/* defining data type to store an ECC coordinate/point in 64bits words: */
|
||||
typedef uint64_t uECC_dword_t;
|
||||
|
||||
/* defining masks useful for ecc computations: */
|
||||
#define HIGH_BIT_SET 0x80000000
|
||||
#define uECC_WORD_BITS 32
|
||||
#define uECC_WORD_BITS_SHIFT 5
|
||||
#define uECC_WORD_BITS_MASK 0x01F
|
||||
|
||||
/* Number of words of 32 bits to represent an element of the the curve p-256: */
|
||||
#define NUM_ECC_WORDS 8
|
||||
/* Number of bytes to represent an element of the the curve p-256: */
|
||||
#define NUM_ECC_BYTES (uECC_WORD_SIZE*NUM_ECC_WORDS)
|
||||
|
||||
/* structure that represents an elliptic curve (e.g. p256):*/
|
||||
struct uECC_Curve_t;
|
||||
typedef const struct uECC_Curve_t * uECC_Curve;
|
||||
struct uECC_Curve_t {
|
||||
wordcount_t num_words;
|
||||
wordcount_t num_bytes;
|
||||
bitcount_t num_n_bits;
|
||||
uECC_word_t p[NUM_ECC_WORDS];
|
||||
uECC_word_t n[NUM_ECC_WORDS];
|
||||
uECC_word_t G[NUM_ECC_WORDS * 2];
|
||||
uECC_word_t b[NUM_ECC_WORDS];
|
||||
void (*double_jacobian)(uECC_word_t * X1, uECC_word_t * Y1, uECC_word_t * Z1,
|
||||
uECC_Curve curve);
|
||||
void (*x_side)(uECC_word_t *result, const uECC_word_t *x, uECC_Curve curve);
|
||||
void (*mmod_fast)(uECC_word_t *result, uECC_word_t *product);
|
||||
};
|
||||
|
||||
/*
|
||||
* @brief computes doubling of point ion jacobian coordinates, in place.
|
||||
* @param X1 IN/OUT -- x coordinate
|
||||
* @param Y1 IN/OUT -- y coordinate
|
||||
* @param Z1 IN/OUT -- z coordinate
|
||||
* @param curve IN -- elliptic curve
|
||||
*/
|
||||
void double_jacobian_default(uECC_word_t * X1, uECC_word_t * Y1,
|
||||
uECC_word_t * Z1, uECC_Curve curve);
|
||||
|
||||
/*
|
||||
* @brief Computes x^3 + ax + b. result must not overlap x.
|
||||
* @param result OUT -- x^3 + ax + b
|
||||
* @param x IN -- value of x
|
||||
* @param curve IN -- elliptic curve
|
||||
*/
|
||||
void x_side_default(uECC_word_t *result, const uECC_word_t *x,
|
||||
uECC_Curve curve);
|
||||
|
||||
/*
|
||||
* @brief Computes result = product % curve_p
|
||||
* from http://www.nsa.gov/ia/_files/nist-routines.pdf
|
||||
* @param result OUT -- product % curve_p
|
||||
* @param product IN -- value to be reduced mod curve_p
|
||||
*/
|
||||
void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int *product);
|
||||
|
||||
/* Bytes to words ordering: */
|
||||
#define BYTES_TO_WORDS_8(a, b, c, d, e, f, g, h) 0x##d##c##b##a, 0x##h##g##f##e
|
||||
#define BYTES_TO_WORDS_4(a, b, c, d) 0x##d##c##b##a
|
||||
#define BITS_TO_WORDS(num_bits) \
|
||||
((num_bits + ((uECC_WORD_SIZE * 8) - 1)) / (uECC_WORD_SIZE * 8))
|
||||
#define BITS_TO_BYTES(num_bits) ((num_bits + 7) / 8)
|
||||
|
||||
/* definition of curve NIST p-256: */
|
||||
static const struct uECC_Curve_t curve_secp256r1 = {
|
||||
NUM_ECC_WORDS,
|
||||
NUM_ECC_BYTES,
|
||||
256, /* num_n_bits */ {
|
||||
BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
|
||||
BYTES_TO_WORDS_8(FF, FF, FF, FF, 00, 00, 00, 00),
|
||||
BYTES_TO_WORDS_8(00, 00, 00, 00, 00, 00, 00, 00),
|
||||
BYTES_TO_WORDS_8(01, 00, 00, 00, FF, FF, FF, FF)
|
||||
}, {
|
||||
BYTES_TO_WORDS_8(51, 25, 63, FC, C2, CA, B9, F3),
|
||||
BYTES_TO_WORDS_8(84, 9E, 17, A7, AD, FA, E6, BC),
|
||||
BYTES_TO_WORDS_8(FF, FF, FF, FF, FF, FF, FF, FF),
|
||||
BYTES_TO_WORDS_8(00, 00, 00, 00, FF, FF, FF, FF)
|
||||
}, {
|
||||
BYTES_TO_WORDS_8(96, C2, 98, D8, 45, 39, A1, F4),
|
||||
BYTES_TO_WORDS_8(A0, 33, EB, 2D, 81, 7D, 03, 77),
|
||||
BYTES_TO_WORDS_8(F2, 40, A4, 63, E5, E6, BC, F8),
|
||||
BYTES_TO_WORDS_8(47, 42, 2C, E1, F2, D1, 17, 6B),
|
||||
|
||||
BYTES_TO_WORDS_8(F5, 51, BF, 37, 68, 40, B6, CB),
|
||||
BYTES_TO_WORDS_8(CE, 5E, 31, 6B, 57, 33, CE, 2B),
|
||||
BYTES_TO_WORDS_8(16, 9E, 0F, 7C, 4A, EB, E7, 8E),
|
||||
BYTES_TO_WORDS_8(9B, 7F, 1A, FE, E2, 42, E3, 4F)
|
||||
}, {
|
||||
BYTES_TO_WORDS_8(4B, 60, D2, 27, 3E, 3C, CE, 3B),
|
||||
BYTES_TO_WORDS_8(F6, B0, 53, CC, B0, 06, 1D, 65),
|
||||
BYTES_TO_WORDS_8(BC, 86, 98, 76, 55, BD, EB, B3),
|
||||
BYTES_TO_WORDS_8(E7, 93, 3A, AA, D8, 35, C6, 5A)
|
||||
},
|
||||
&double_jacobian_default,
|
||||
&x_side_default,
|
||||
&vli_mmod_fast_secp256r1
|
||||
};
|
||||
|
||||
uECC_Curve uECC_secp256r1(void);
|
||||
|
||||
/*
|
||||
* @brief Generates a random integer in the range 0 < random < top.
|
||||
* Both random and top have num_words words.
|
||||
* @param random OUT -- random integer in the range 0 < random < top
|
||||
* @param top IN -- upper limit
|
||||
* @param num_words IN -- number of words
|
||||
* @return a random integer in the range 0 < random < top
|
||||
*/
|
||||
int uECC_generate_random_int(uECC_word_t *random, const uECC_word_t *top,
|
||||
wordcount_t num_words);
|
||||
|
||||
|
||||
/* uECC_RNG_Function type
|
||||
* The RNG function should fill 'size' random bytes into 'dest'. It should
|
||||
* return 1 if 'dest' was filled with random data, or 0 if the random data could
|
||||
* not be generated. The filled-in values should be either truly random, or from
|
||||
* a cryptographically-secure PRNG.
|
||||
*
|
||||
* A correctly functioning RNG function must be set (using uECC_set_rng())
|
||||
* before calling uECC_make_key() or uECC_sign().
|
||||
*
|
||||
* Setting a correctly functioning RNG function improves the resistance to
|
||||
* side-channel attacks for uECC_shared_secret().
|
||||
*
|
||||
* A correct RNG function is set by default. If you are building on another
|
||||
* POSIX-compliant system that supports /dev/random or /dev/urandom, you can
|
||||
* define uECC_POSIX to use the predefined RNG.
|
||||
*/
|
||||
typedef int(*uECC_RNG_Function)(uint8_t *dest, unsigned int size);
|
||||
|
||||
/*
|
||||
* @brief Set the function that will be used to generate random bytes. The RNG
|
||||
* function should return 1 if the random data was generated, or 0 if the random
|
||||
* data could not be generated.
|
||||
*
|
||||
* @note On platforms where there is no predefined RNG function, this must be
|
||||
* called before uECC_make_key() or uECC_sign() are used.
|
||||
*
|
||||
* @param rng_function IN -- function that will be used to generate random bytes
|
||||
*/
|
||||
void uECC_set_rng(uECC_RNG_Function rng_function);
|
||||
|
||||
/*
|
||||
* @brief provides current uECC_RNG_Function.
|
||||
* @return Returns the function that will be used to generate random bytes.
|
||||
*/
|
||||
uECC_RNG_Function uECC_get_rng(void);
|
||||
|
||||
/*
|
||||
* @brief computes the size of a private key for the curve in bytes.
|
||||
* @param curve IN -- elliptic curve
|
||||
* @return size of a private key for the curve in bytes.
|
||||
*/
|
||||
int uECC_curve_private_key_size(uECC_Curve curve);
|
||||
|
||||
/*
|
||||
* @brief computes the size of a public key for the curve in bytes.
|
||||
* @param curve IN -- elliptic curve
|
||||
* @return the size of a public key for the curve in bytes.
|
||||
*/
|
||||
int uECC_curve_public_key_size(uECC_Curve curve);
|
||||
|
||||
/*
|
||||
* @brief Compute the corresponding public key for a private key.
|
||||
* @param private_key IN -- The private key to compute the public key for
|
||||
* @param public_key OUT -- Will be filled in with the corresponding public key
|
||||
* @param curve
|
||||
* @return Returns 1 if key was computed successfully, 0 if an error occurred.
|
||||
*/
|
||||
int uECC_compute_public_key(const uint8_t *private_key,
|
||||
uint8_t *public_key, uECC_Curve curve);
|
||||
|
||||
/*
|
||||
* @brief Compute public-key.
|
||||
* @return corresponding public-key.
|
||||
* @param result OUT -- public-key
|
||||
* @param private_key IN -- private-key
|
||||
* @param curve IN -- elliptic curve
|
||||
*/
|
||||
uECC_word_t EccPoint_compute_public_key(uECC_word_t *result,
|
||||
uECC_word_t *private_key, uECC_Curve curve);
|
||||
|
||||
/*
|
||||
* @brief Regularize the bitcount for the private key so that attackers cannot
|
||||
* use a side channel attack to learn the number of leading zeros.
|
||||
* @return Regularized k
|
||||
* @param k IN -- private-key
|
||||
* @param k0 IN/OUT -- regularized k
|
||||
* @param k1 IN/OUT -- regularized k
|
||||
* @param curve IN -- elliptic curve
|
||||
*/
|
||||
uECC_word_t regularize_k(const uECC_word_t * const k, uECC_word_t *k0,
|
||||
uECC_word_t *k1, uECC_Curve curve);
|
||||
|
||||
/*
|
||||
* @brief Point multiplication algorithm using Montgomery's ladder with co-Z
|
||||
* coordinates. See http://eprint.iacr.org/2011/338.pdf.
|
||||
* @note Result may overlap point.
|
||||
* @param result OUT -- returns scalar*point
|
||||
* @param point IN -- elliptic curve point
|
||||
* @param scalar IN -- scalar
|
||||
* @param initial_Z IN -- initial value for z
|
||||
* @param num_bits IN -- number of bits in scalar
|
||||
* @param curve IN -- elliptic curve
|
||||
*/
|
||||
void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point,
|
||||
const uECC_word_t * scalar, const uECC_word_t * initial_Z,
|
||||
bitcount_t num_bits, uECC_Curve curve);
|
||||
|
||||
/*
|
||||
* @brief Constant-time comparison to zero - secure way to compare long integers
|
||||
* @param vli IN -- very long integer
|
||||
* @param num_words IN -- number of words in the vli
|
||||
* @return 1 if vli == 0, 0 otherwise.
|
||||
*/
|
||||
uECC_word_t uECC_vli_isZero(const uECC_word_t *vli, wordcount_t num_words);
|
||||
|
||||
/*
|
||||
* @brief Check if 'point' is the point at infinity
|
||||
* @param point IN -- elliptic curve point
|
||||
* @param curve IN -- elliptic curve
|
||||
* @return if 'point' is the point at infinity, 0 otherwise.
|
||||
*/
|
||||
uECC_word_t EccPoint_isZero(const uECC_word_t *point, uECC_Curve curve);
|
||||
|
||||
/*
|
||||
* @brief computes the sign of left - right, in constant time.
|
||||
* @param left IN -- left term to be compared
|
||||
* @param right IN -- right term to be compared
|
||||
* @param num_words IN -- number of words
|
||||
* @return the sign of left - right
|
||||
*/
|
||||
cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right,
|
||||
wordcount_t num_words);
|
||||
|
||||
/*
|
||||
* @brief computes sign of left - right, not in constant time.
|
||||
* @note should not be used if inputs are part of a secret
|
||||
* @param left IN -- left term to be compared
|
||||
* @param right IN -- right term to be compared
|
||||
* @param num_words IN -- number of words
|
||||
* @return the sign of left - right
|
||||
*/
|
||||
cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left, const uECC_word_t *right,
|
||||
wordcount_t num_words);
|
||||
|
||||
/*
|
||||
* @brief Computes result = (left - right) % mod.
|
||||
* @note Assumes that (left < mod) and (right < mod), and that result does not
|
||||
* overlap mod.
|
||||
* @param result OUT -- (left - right) % mod
|
||||
* @param left IN -- leftright term in modular subtraction
|
||||
* @param right IN -- right term in modular subtraction
|
||||
* @param mod IN -- mod
|
||||
* @param num_words IN -- number of words
|
||||
*/
|
||||
void uECC_vli_modSub(uECC_word_t *result, const uECC_word_t *left,
|
||||
const uECC_word_t *right, const uECC_word_t *mod,
|
||||
wordcount_t num_words);
|
||||
|
||||
/*
|
||||
* @brief Computes P' = (x1', y1', Z3), P + Q = (x3, y3, Z3) or
|
||||
* P => P', Q => P + Q
|
||||
* @note assumes Input P = (x1, y1, Z), Q = (x2, y2, Z)
|
||||
* @param X1 IN -- x coordinate of P
|
||||
* @param Y1 IN -- y coordinate of P
|
||||
* @param X2 IN -- x coordinate of Q
|
||||
* @param Y2 IN -- y coordinate of Q
|
||||
* @param curve IN -- elliptic curve
|
||||
*/
|
||||
void XYcZ_add(uECC_word_t * X1, uECC_word_t * Y1, uECC_word_t * X2,
|
||||
uECC_word_t * Y2, uECC_Curve curve);
|
||||
|
||||
/*
|
||||
* @brief Computes (x1 * z^2, y1 * z^3)
|
||||
* @param X1 IN -- previous x1 coordinate
|
||||
* @param Y1 IN -- previous y1 coordinate
|
||||
* @param Z IN -- z value
|
||||
* @param curve IN -- elliptic curve
|
||||
*/
|
||||
void apply_z(uECC_word_t * X1, uECC_word_t * Y1, const uECC_word_t * const Z,
|
||||
uECC_Curve curve);
|
||||
|
||||
/*
|
||||
* @brief Check if bit is set.
|
||||
* @return Returns nonzero if bit 'bit' of vli is set.
|
||||
* @warning It is assumed that the value provided in 'bit' is within the
|
||||
* boundaries of the word-array 'vli'.
|
||||
* @note The bit ordering layout assumed for vli is: {31, 30, ..., 0},
|
||||
* {63, 62, ..., 32}, {95, 94, ..., 64}, {127, 126,..., 96} for a vli consisting
|
||||
* of 4 uECC_word_t elements.
|
||||
*/
|
||||
uECC_word_t uECC_vli_testBit(const uECC_word_t *vli, bitcount_t bit);
|
||||
|
||||
/*
|
||||
* @brief Computes result = product % mod, where product is 2N words long.
|
||||
* @param result OUT -- product % mod
|
||||
* @param mod IN -- module
|
||||
* @param num_words IN -- number of words
|
||||
* @warning Currently only designed to work for curve_p or curve_n.
|
||||
*/
|
||||
void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product,
|
||||
const uECC_word_t *mod, wordcount_t num_words);
|
||||
|
||||
/*
|
||||
* @brief Computes modular product (using curve->mmod_fast)
|
||||
* @param result OUT -- (left * right) mod % curve_p
|
||||
* @param left IN -- left term in product
|
||||
* @param right IN -- right term in product
|
||||
* @param curve IN -- elliptic curve
|
||||
*/
|
||||
void uECC_vli_modMult_fast(uECC_word_t *result, const uECC_word_t *left,
|
||||
const uECC_word_t *right, uECC_Curve curve);
|
||||
|
||||
/*
|
||||
* @brief Computes result = left - right.
|
||||
* @note Can modify in place.
|
||||
* @param result OUT -- left - right
|
||||
* @param left IN -- left term in subtraction
|
||||
* @param right IN -- right term in subtraction
|
||||
* @param num_words IN -- number of words
|
||||
* @return borrow
|
||||
*/
|
||||
uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left,
|
||||
const uECC_word_t *right, wordcount_t num_words);
|
||||
|
||||
/*
|
||||
* @brief Constant-time comparison function(secure way to compare long ints)
|
||||
* @param left IN -- left term in comparison
|
||||
* @param right IN -- right term in comparison
|
||||
* @param num_words IN -- number of words
|
||||
* @return Returns 0 if left == right, 1 otherwise.
|
||||
*/
|
||||
uECC_word_t uECC_vli_equal(const uECC_word_t *left, const uECC_word_t *right,
|
||||
wordcount_t num_words);
|
||||
|
||||
/*
|
||||
* @brief Computes (left * right) % mod
|
||||
* @param result OUT -- (left * right) % mod
|
||||
* @param left IN -- left term in product
|
||||
* @param right IN -- right term in product
|
||||
* @param mod IN -- mod
|
||||
* @param num_words IN -- number of words
|
||||
*/
|
||||
void uECC_vli_modMult(uECC_word_t *result, const uECC_word_t *left,
|
||||
const uECC_word_t *right, const uECC_word_t *mod,
|
||||
wordcount_t num_words);
|
||||
|
||||
/*
|
||||
* @brief Computes (1 / input) % mod
|
||||
* @note All VLIs are the same size.
|
||||
* @note See "Euclid's GCD to Montgomery Multiplication to the Great Divide"
|
||||
* @param result OUT -- (1 / input) % mod
|
||||
* @param input IN -- value to be modular inverted
|
||||
* @param mod IN -- mod
|
||||
* @param num_words -- number of words
|
||||
*/
|
||||
void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input,
|
||||
const uECC_word_t *mod, wordcount_t num_words);
|
||||
|
||||
/*
|
||||
* @brief Sets dest = src.
|
||||
* @param dest OUT -- destination buffer
|
||||
* @param src IN -- origin buffer
|
||||
* @param num_words IN -- number of words
|
||||
*/
|
||||
void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src,
|
||||
wordcount_t num_words);
|
||||
|
||||
/*
|
||||
* @brief Computes (left + right) % mod.
|
||||
* @note Assumes that (left < mod) and right < mod), and that result does not
|
||||
* overlap mod.
|
||||
* @param result OUT -- (left + right) % mod.
|
||||
* @param left IN -- left term in addition
|
||||
* @param right IN -- right term in addition
|
||||
* @param mod IN -- mod
|
||||
* @param num_words IN -- number of words
|
||||
*/
|
||||
void uECC_vli_modAdd(uECC_word_t *result, const uECC_word_t *left,
|
||||
const uECC_word_t *right, const uECC_word_t *mod,
|
||||
wordcount_t num_words);
|
||||
|
||||
/*
|
||||
* @brief Counts the number of bits required to represent vli.
|
||||
* @param vli IN -- very long integer
|
||||
* @param max_words IN -- number of words
|
||||
* @return number of bits in given vli
|
||||
*/
|
||||
bitcount_t uECC_vli_numBits(const uECC_word_t *vli,
|
||||
const wordcount_t max_words);
|
||||
|
||||
/*
|
||||
* @brief Erases (set to 0) vli
|
||||
* @param vli IN -- very long integer
|
||||
* @param num_words IN -- number of words
|
||||
*/
|
||||
void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words);
|
||||
|
||||
/*
|
||||
* @brief check if it is a valid point in the curve
|
||||
* @param point IN -- point to be checked
|
||||
* @param curve IN -- elliptic curve
|
||||
* @return 0 if point is valid
|
||||
* @exception returns -1 if it is a point at infinity
|
||||
* @exception returns -2 if x or y is smaller than p,
|
||||
* @exception returns -3 if y^2 != x^3 + ax + b.
|
||||
*/
|
||||
int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve);
|
||||
|
||||
/*
|
||||
* @brief Check if a public key is valid.
|
||||
* @param public_key IN -- The public key to be checked.
|
||||
* @return returns 0 if the public key is valid
|
||||
* @exception returns -1 if it is a point at infinity
|
||||
* @exception returns -2 if x or y is smaller than p,
|
||||
* @exception returns -3 if y^2 != x^3 + ax + b.
|
||||
* @exception returns -4 if public key is the group generator.
|
||||
*
|
||||
* @note Note that you are not required to check for a valid public key before
|
||||
* using any other uECC functions. However, you may wish to avoid spending CPU
|
||||
* time computing a shared secret or verifying a signature using an invalid
|
||||
* public key.
|
||||
*/
|
||||
int uECC_valid_public_key(const uint8_t *public_key, uECC_Curve curve);
|
||||
|
||||
/*
|
||||
* @brief Converts an integer in uECC native format to big-endian bytes.
|
||||
* @param bytes OUT -- bytes representation
|
||||
* @param num_bytes IN -- number of bytes
|
||||
* @param native IN -- uECC native representation
|
||||
*/
|
||||
void uECC_vli_nativeToBytes(uint8_t *bytes, int num_bytes,
|
||||
const unsigned int *native);
|
||||
|
||||
/*
|
||||
* @brief Converts big-endian bytes to an integer in uECC native format.
|
||||
* @param native OUT -- uECC native representation
|
||||
* @param bytes IN -- bytes representation
|
||||
* @param num_bytes IN -- number of bytes
|
||||
*/
|
||||
void uECC_vli_bytesToNative(unsigned int *native, const uint8_t *bytes,
|
||||
int num_bytes);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __TC_UECC_H__ */
|
||||
@@ -0,0 +1,131 @@
|
||||
/* ecc_dh.h - TinyCrypt interface to EC-DH implementation */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2014, Kenneth MacKay
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief -- Interface to EC-DH implementation.
|
||||
*
|
||||
* Overview: This software is an implementation of EC-DH. This implementation
|
||||
* uses curve NIST p-256.
|
||||
*
|
||||
* Security: The curve NIST p-256 provides approximately 128 bits of security.
|
||||
*/
|
||||
|
||||
#ifndef __TC_ECC_DH_H__
|
||||
#define __TC_ECC_DH_H__
|
||||
|
||||
#include "ecc.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Create a public/private key pair.
|
||||
* @return returns TC_CRYPTO_SUCCESS (1) if the key pair was generated successfully
|
||||
* returns TC_CRYPTO_FAIL (0) if error while generating key pair
|
||||
*
|
||||
* @param p_public_key OUT -- Will be filled in with the public key. Must be at
|
||||
* least 2 * the curve size (in bytes) long. For curve secp256r1, p_public_key
|
||||
* must be 64 bytes long.
|
||||
* @param p_private_key OUT -- Will be filled in with the private key. Must be as
|
||||
* long as the curve order (for secp256r1, p_private_key must be 32 bytes long).
|
||||
*
|
||||
* @note side-channel countermeasure: algorithm strengthened against timing
|
||||
* attack.
|
||||
* @warning A cryptographically-secure PRNG function must be set (using
|
||||
* uECC_set_rng()) before calling uECC_make_key().
|
||||
*/
|
||||
int uECC_make_key(uint8_t *p_public_key, uint8_t *p_private_key, uECC_Curve curve);
|
||||
|
||||
#ifdef ENABLE_TESTS
|
||||
|
||||
/**
|
||||
* @brief Create a public/private key pair given a specific d.
|
||||
*
|
||||
* @note THIS FUNCTION SHOULD BE CALLED ONLY FOR TEST PURPOSES. Refer to
|
||||
* uECC_make_key() function for real applications.
|
||||
*/
|
||||
int uECC_make_key_with_d(uint8_t *p_public_key, uint8_t *p_private_key,
|
||||
unsigned int *d, uECC_Curve curve);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Compute a shared secret given your secret key and someone else's
|
||||
* public key.
|
||||
* @return returns TC_CRYPTO_SUCCESS (1) if the shared secret was computed successfully
|
||||
* returns TC_CRYPTO_FAIL (0) otherwise
|
||||
*
|
||||
* @param p_secret OUT -- Will be filled in with the shared secret value. Must be
|
||||
* the same size as the curve size (for curve secp256r1, secret must be 32 bytes
|
||||
* long.
|
||||
* @param p_public_key IN -- The public key of the remote party.
|
||||
* @param p_private_key IN -- Your private key.
|
||||
*
|
||||
* @warning It is recommended to use the output of uECC_shared_secret() as the
|
||||
* input of a recommended Key Derivation Function (see NIST SP 800-108) in
|
||||
* order to produce a cryptographically secure symmetric key.
|
||||
*/
|
||||
int uECC_shared_secret(const uint8_t *p_public_key, const uint8_t *p_private_key,
|
||||
uint8_t *p_secret, uECC_Curve curve);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __TC_ECC_DH_H__ */
|
||||
@@ -0,0 +1,139 @@
|
||||
/* ecc_dh.h - TinyCrypt interface to EC-DSA implementation */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2014, Kenneth MacKay
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief -- Interface to EC-DSA implementation.
|
||||
*
|
||||
* Overview: This software is an implementation of EC-DSA. This implementation
|
||||
* uses curve NIST p-256.
|
||||
*
|
||||
* Security: The curve NIST p-256 provides approximately 128 bits of security.
|
||||
*
|
||||
* Usage: - To sign: Compute a hash of the data you wish to sign (SHA-2 is
|
||||
* recommended) and pass it in to ecdsa_sign function along with your
|
||||
* private key and a random number. You must use a new non-predictable
|
||||
* random number to generate each new signature.
|
||||
* - To verify a signature: Compute the hash of the signed data using
|
||||
* the same hash as the signer and pass it to this function along with
|
||||
* the signer's public key and the signature values (r and s).
|
||||
*/
|
||||
|
||||
#ifndef __TC_ECC_DSA_H__
|
||||
#define __TC_ECC_DSA_H__
|
||||
|
||||
#include "ecc.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Generate an ECDSA signature for a given hash value.
|
||||
* @return returns TC_CRYPTO_SUCCESS (1) if the signature generated successfully
|
||||
* returns TC_CRYPTO_FAIL (0) if an error occurred.
|
||||
*
|
||||
* @param p_private_key IN -- Your private key.
|
||||
* @param p_message_hash IN -- The hash of the message to sign.
|
||||
* @param p_hash_size IN -- The size of p_message_hash in bytes.
|
||||
* @param p_signature OUT -- Will be filled in with the signature value. Must be
|
||||
* at least 2 * curve size long (for secp256r1, signature must be 64 bytes long).
|
||||
*
|
||||
* @warning A cryptographically-secure PRNG function must be set (using
|
||||
* uECC_set_rng()) before calling uECC_sign().
|
||||
* @note Usage: Compute a hash of the data you wish to sign (SHA-2 is
|
||||
* recommended) and pass it in to this function along with your private key.
|
||||
* @note side-channel countermeasure: algorithm strengthened against timing
|
||||
* attack.
|
||||
*/
|
||||
int uECC_sign(const uint8_t *p_private_key, const uint8_t *p_message_hash,
|
||||
unsigned p_hash_size, uint8_t *p_signature, uECC_Curve curve);
|
||||
|
||||
#ifdef ENABLE_TESTS
|
||||
/*
|
||||
* THIS FUNCTION SHOULD BE CALLED FOR TEST PURPOSES ONLY.
|
||||
* Refer to uECC_sign() function for real applications.
|
||||
*/
|
||||
int uECC_sign_with_k(const uint8_t *private_key, const uint8_t *message_hash,
|
||||
unsigned int hash_size, uECC_word_t *k, uint8_t *signature,
|
||||
uECC_Curve curve);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Verify an ECDSA signature.
|
||||
* @return returns TC_SUCCESS (1) if the signature is valid
|
||||
* returns TC_FAIL (0) if the signature is invalid.
|
||||
*
|
||||
* @param p_public_key IN -- The signer's public key.
|
||||
* @param p_message_hash IN -- The hash of the signed data.
|
||||
* @param p_hash_size IN -- The size of p_message_hash in bytes.
|
||||
* @param p_signature IN -- The signature values.
|
||||
*
|
||||
* @note Usage: Compute the hash of the signed data using the same hash as the
|
||||
* signer and pass it to this function along with the signer's public key and
|
||||
* the signature values (hash_size and signature).
|
||||
*/
|
||||
int uECC_verify(const uint8_t *p_public_key, const uint8_t *p_message_hash,
|
||||
unsigned int p_hash_size, const uint8_t *p_signature, uECC_Curve curve);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __TC_ECC_DSA_H__ */
|
||||
@@ -0,0 +1,81 @@
|
||||
/* uECC_platform_specific.h - Interface to platform specific functions*/
|
||||
|
||||
/* Copyright (c) 2014, Kenneth MacKay
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* uECC_platform_specific.h -- Interface to platform specific functions
|
||||
*/
|
||||
|
||||
#ifndef __UECC_PLATFORM_SPECIFIC_H_
|
||||
#define __UECC_PLATFORM_SPECIFIC_H_
|
||||
|
||||
/*
|
||||
* The RNG function should fill 'size' random bytes into 'dest'. It should
|
||||
* return 1 if 'dest' was filled with random data, or 0 if the random data could
|
||||
* not be generated. The filled-in values should be either truly random, or from
|
||||
* a cryptographically-secure PRNG.
|
||||
*
|
||||
* A cryptographically-secure PRNG function must be set (using uECC_set_rng())
|
||||
* before calling uECC_make_key() or uECC_sign().
|
||||
*
|
||||
* Setting a cryptographically-secure PRNG function improves the resistance to
|
||||
* side-channel attacks for uECC_shared_secret().
|
||||
*
|
||||
* A correct PRNG function is set by default (default_RNG_defined = 1) and works
|
||||
* for some platforms, such as Unix and Linux. For other platforms, you may need
|
||||
* to provide another PRNG function.
|
||||
*/
|
||||
#define default_RNG_defined 0
|
||||
|
||||
int default_CSPRNG(uint8_t *dest, unsigned int size);
|
||||
|
||||
#endif /* __UECC_PLATFORM_SPECIFIC_H_ */
|
||||
@@ -0,0 +1,139 @@
|
||||
/* hmac.h - TinyCrypt interface to an HMAC implementation */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Interface to an HMAC implementation.
|
||||
*
|
||||
* Overview: HMAC is a message authentication code based on hash functions.
|
||||
* TinyCrypt hard codes SHA-256 as the hash function. A message
|
||||
* authentication code based on hash functions is also called a
|
||||
* keyed cryptographic hash function since it performs a
|
||||
* transformation specified by a key in an arbitrary length data
|
||||
* set into a fixed length data set (also called tag).
|
||||
*
|
||||
* Security: The security of the HMAC depends on the length of the key and
|
||||
* on the security of the hash function. Note that HMAC primitives
|
||||
* are much less affected by collision attacks than their
|
||||
* corresponding hash functions.
|
||||
*
|
||||
* Requires: SHA-256
|
||||
*
|
||||
* Usage: 1) call tc_hmac_set_key to set the HMAC key.
|
||||
*
|
||||
* 2) call tc_hmac_init to initialize a struct hash_state before
|
||||
* processing the data.
|
||||
*
|
||||
* 3) call tc_hmac_update to process the next input segment;
|
||||
* tc_hmac_update can be called as many times as needed to process
|
||||
* all of the segments of the input; the order is important.
|
||||
*
|
||||
* 4) call tc_hmac_final to out put the tag.
|
||||
*/
|
||||
|
||||
#ifndef __TC_HMAC_H__
|
||||
#define __TC_HMAC_H__
|
||||
|
||||
#include "sha256.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct tc_hmac_state_struct {
|
||||
/* the internal state required by h */
|
||||
struct tc_sha256_state_struct hash_state;
|
||||
/* HMAC key schedule */
|
||||
uint8_t key[2*TC_SHA256_BLOCK_SIZE];
|
||||
};
|
||||
typedef struct tc_hmac_state_struct *TCHmacState_t;
|
||||
|
||||
/**
|
||||
* @brief HMAC set key procedure
|
||||
* Configures ctx to use key
|
||||
* @return returns TC_CRYPTO_SUCCESS (1)
|
||||
* returns TC_CRYPTO_FAIL (0) if
|
||||
* ctx == NULL or
|
||||
* key == NULL or
|
||||
* key_size == 0
|
||||
* @param ctx IN/OUT -- the struct tc_hmac_state_struct to initial
|
||||
* @param key IN -- the HMAC key to configure
|
||||
* @param key_size IN -- the HMAC key size
|
||||
*/
|
||||
int tc_hmac_set_key(TCHmacState_t ctx, const uint8_t *key,
|
||||
unsigned int key_size);
|
||||
|
||||
/**
|
||||
* @brief HMAC initialize procedure
|
||||
* Initializes ctx to begin the next HMAC operation
|
||||
* @return returns TC_CRYPTO_SUCCESS (1)
|
||||
* returns TC_CRYPTO_FAIL (0) if: ctx == NULL or key == NULL
|
||||
* @param ctx IN/OUT -- struct tc_hmac_state_struct buffer to initialize
|
||||
*/
|
||||
int tc_hmac_init(TCHmacState_t ctx);
|
||||
|
||||
/**
|
||||
* @brief HMAC update procedure
|
||||
* Mixes data_length bytes addressed by data into state
|
||||
* @return returns TC_CRYPTO_SUCCCESS (1)
|
||||
* returns TC_CRYPTO_FAIL (0) if: ctx == NULL or key == NULL
|
||||
* @note Assumes state has been initialized by tc_hmac_init
|
||||
* @param ctx IN/OUT -- state of HMAC computation so far
|
||||
* @param data IN -- data to incorporate into state
|
||||
* @param data_length IN -- size of data in bytes
|
||||
*/
|
||||
int tc_hmac_update(TCHmacState_t ctx, const void *data,
|
||||
unsigned int data_length);
|
||||
|
||||
/**
|
||||
* @brief HMAC final procedure
|
||||
* Writes the HMAC tag into the tag buffer
|
||||
* @return returns TC_CRYPTO_SUCCESS (1)
|
||||
* returns TC_CRYPTO_FAIL (0) if:
|
||||
* tag == NULL or
|
||||
* ctx == NULL or
|
||||
* key == NULL or
|
||||
* taglen != TC_SHA256_DIGEST_SIZE
|
||||
* @note ctx is erased before exiting. This should never be changed/removed.
|
||||
* @note Assumes the tag bufer is at least sizeof(hmac_tag_size(state)) bytes
|
||||
* state has been initialized by tc_hmac_init
|
||||
* @param tag IN/OUT -- buffer to receive computed HMAC tag
|
||||
* @param taglen IN -- size of tag in bytes
|
||||
* @param ctx IN/OUT -- the HMAC state for computing tag
|
||||
*/
|
||||
int tc_hmac_final(uint8_t *tag, unsigned int taglen, TCHmacState_t ctx);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /*__TC_HMAC_H__*/
|
||||
@@ -0,0 +1,164 @@
|
||||
/* hmac_prng.h - TinyCrypt interface to an HMAC-PRNG implementation */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Interface to an HMAC-PRNG implementation.
|
||||
*
|
||||
* Overview: A pseudo-random number generator (PRNG) generates a sequence
|
||||
* of numbers that have a distribution close to the one expected
|
||||
* for a sequence of truly random numbers. The NIST Special
|
||||
* Publication 800-90A specifies several mechanisms to generate
|
||||
* sequences of pseudo random numbers, including the HMAC-PRNG one
|
||||
* which is based on HMAC. TinyCrypt implements HMAC-PRNG with
|
||||
* certain modifications from the NIST SP 800-90A spec.
|
||||
*
|
||||
* Security: A cryptographically secure PRNG depends on the existence of an
|
||||
* entropy source to provide a truly random seed as well as the
|
||||
* security of the primitives used as the building blocks (HMAC and
|
||||
* SHA256, for TinyCrypt).
|
||||
*
|
||||
* The NIST SP 800-90A standard tolerates a null personalization,
|
||||
* while TinyCrypt requires a non-null personalization. This is
|
||||
* because a personalization string (the host name concatenated
|
||||
* with a time stamp, for example) is easily computed and might be
|
||||
* the last line of defense against failure of the entropy source.
|
||||
*
|
||||
* Requires: - SHA-256
|
||||
* - HMAC
|
||||
*
|
||||
* Usage: 1) call tc_hmac_prng_init to set the HMAC key and process the
|
||||
* personalization data.
|
||||
*
|
||||
* 2) call tc_hmac_prng_reseed to process the seed and additional
|
||||
* input.
|
||||
*
|
||||
* 3) call tc_hmac_prng_generate to out put the pseudo-random data.
|
||||
*/
|
||||
|
||||
#ifndef __TC_HMAC_PRNG_H__
|
||||
#define __TC_HMAC_PRNG_H__
|
||||
|
||||
#include "sha256.h"
|
||||
#include "hmac.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define TC_HMAC_PRNG_RESEED_REQ -1
|
||||
|
||||
struct tc_hmac_prng_struct {
|
||||
/* the HMAC instance for this PRNG */
|
||||
struct tc_hmac_state_struct h;
|
||||
/* the PRNG key */
|
||||
uint8_t key[TC_SHA256_DIGEST_SIZE];
|
||||
/* PRNG state */
|
||||
uint8_t v[TC_SHA256_DIGEST_SIZE];
|
||||
/* calls to tc_hmac_prng_generate left before re-seed */
|
||||
unsigned int countdown;
|
||||
};
|
||||
|
||||
typedef struct tc_hmac_prng_struct *TCHmacPrng_t;
|
||||
|
||||
/**
|
||||
* @brief HMAC-PRNG initialization procedure
|
||||
* Initializes prng with personalization, disables tc_hmac_prng_generate
|
||||
* @return returns TC_CRYPTO_SUCCESS (1)
|
||||
* returns TC_CRYPTO_FAIL (0) if:
|
||||
* prng == NULL,
|
||||
* personalization == NULL,
|
||||
* plen > MAX_PLEN
|
||||
* @note Assumes: - personalization != NULL.
|
||||
* The personalization is a platform unique string (e.g., the host
|
||||
* name) and is the last line of defense against failure of the
|
||||
* entropy source
|
||||
* @warning NIST SP 800-90A specifies 3 items as seed material during
|
||||
* initialization: entropy seed, personalization, and an optional
|
||||
* nonce. TinyCrypts requires instead a non-null personalization
|
||||
* (which is easily computed) and indirectly requires an entropy
|
||||
* seed (since the reseed function is mandatorily called after
|
||||
* initialize)
|
||||
* @param prng IN/OUT -- the PRNG state to initialize
|
||||
* @param personalization IN -- personalization string
|
||||
* @param plen IN -- personalization length in bytes
|
||||
*/
|
||||
int tc_hmac_prng_init(TCHmacPrng_t prng,
|
||||
const uint8_t *personalization,
|
||||
unsigned int plen);
|
||||
|
||||
/**
|
||||
* @brief HMAC-PRNG reseed procedure
|
||||
* Mixes seed into prng, enables tc_hmac_prng_generate
|
||||
* @return returns TC_CRYPTO_SUCCESS (1)
|
||||
* returns TC_CRYPTO_FAIL (0) if:
|
||||
* prng == NULL,
|
||||
* seed == NULL,
|
||||
* seedlen < MIN_SLEN,
|
||||
* seendlen > MAX_SLEN,
|
||||
* additional_input != (const uint8_t *) 0 && additionallen == 0,
|
||||
* additional_input != (const uint8_t *) 0 && additionallen > MAX_ALEN
|
||||
* @note Assumes:- tc_hmac_prng_init has been called for prng
|
||||
* - seed has sufficient entropy.
|
||||
*
|
||||
* @param prng IN/OUT -- the PRNG state
|
||||
* @param seed IN -- entropy to mix into the prng
|
||||
* @param seedlen IN -- length of seed in bytes
|
||||
* @param additional_input IN -- additional input to the prng
|
||||
* @param additionallen IN -- additional input length in bytes
|
||||
*/
|
||||
int tc_hmac_prng_reseed(TCHmacPrng_t prng, const uint8_t *seed,
|
||||
unsigned int seedlen, const uint8_t *additional_input,
|
||||
unsigned int additionallen);
|
||||
|
||||
/**
|
||||
* @brief HMAC-PRNG generate procedure
|
||||
* Generates outlen pseudo-random bytes into out buffer, updates prng
|
||||
* @return returns TC_CRYPTO_SUCCESS (1)
|
||||
* returns TC_HMAC_PRNG_RESEED_REQ (-1) if a reseed is needed
|
||||
* returns TC_CRYPTO_FAIL (0) if:
|
||||
* out == NULL,
|
||||
* prng == NULL,
|
||||
* outlen == 0,
|
||||
* outlen >= MAX_OUT
|
||||
* @note Assumes tc_hmac_prng_init has been called for prng
|
||||
* @param out IN/OUT -- buffer to receive output
|
||||
* @param outlen IN -- size of out buffer in bytes
|
||||
* @param prng IN/OUT -- the PRNG state
|
||||
*/
|
||||
int tc_hmac_prng_generate(uint8_t *out, unsigned int outlen, TCHmacPrng_t prng);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __TC_HMAC_PRNG_H__ */
|
||||
@@ -0,0 +1,129 @@
|
||||
/* sha256.h - TinyCrypt interface to a SHA-256 implementation */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Interface to a SHA-256 implementation.
|
||||
*
|
||||
* Overview: SHA-256 is a NIST approved cryptographic hashing algorithm
|
||||
* specified in FIPS 180. A hash algorithm maps data of arbitrary
|
||||
* size to data of fixed length.
|
||||
*
|
||||
* Security: SHA-256 provides 128 bits of security against collision attacks
|
||||
* and 256 bits of security against pre-image attacks. SHA-256 does
|
||||
* NOT behave like a random oracle, but it can be used as one if
|
||||
* the string being hashed is prefix-free encoded before hashing.
|
||||
*
|
||||
* Usage: 1) call tc_sha256_init to initialize a struct
|
||||
* tc_sha256_state_struct before hashing a new string.
|
||||
*
|
||||
* 2) call tc_sha256_update to hash the next string segment;
|
||||
* tc_sha256_update can be called as many times as needed to hash
|
||||
* all of the segments of a string; the order is important.
|
||||
*
|
||||
* 3) call tc_sha256_final to out put the digest from a hashing
|
||||
* operation.
|
||||
*/
|
||||
|
||||
#ifndef __TC_SHA256_H__
|
||||
#define __TC_SHA256_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define TC_SHA256_BLOCK_SIZE (64)
|
||||
#define TC_SHA256_DIGEST_SIZE (32)
|
||||
#define TC_SHA256_STATE_BLOCKS (TC_SHA256_DIGEST_SIZE/4)
|
||||
|
||||
struct tc_sha256_state_struct {
|
||||
unsigned int iv[TC_SHA256_STATE_BLOCKS];
|
||||
uint64_t bits_hashed;
|
||||
uint8_t leftover[TC_SHA256_BLOCK_SIZE];
|
||||
size_t leftover_offset;
|
||||
};
|
||||
|
||||
typedef struct tc_sha256_state_struct *TCSha256State_t;
|
||||
|
||||
/**
|
||||
* @brief SHA256 initialization procedure
|
||||
* Initializes s
|
||||
* @return returns TC_CRYPTO_SUCCESS (1)
|
||||
* returns TC_CRYPTO_FAIL (0) if s == NULL
|
||||
* @param s Sha256 state struct
|
||||
*/
|
||||
int tc_sha256_init(TCSha256State_t s);
|
||||
|
||||
/**
|
||||
* @brief SHA256 update procedure
|
||||
* Hashes data_length bytes addressed by data into state s
|
||||
* @return returns TC_CRYPTO_SUCCESS (1)
|
||||
* returns TC_CRYPTO_FAIL (0) if:
|
||||
* s == NULL,
|
||||
* s->iv == NULL,
|
||||
* data == NULL
|
||||
* @note Assumes s has been initialized by tc_sha256_init
|
||||
* @warning The state buffer 'leftover' is left in memory after processing
|
||||
* If your application intends to have sensitive data in this
|
||||
* buffer, remind to erase it after the data has been processed
|
||||
* @param s Sha256 state struct
|
||||
* @param data message to hash
|
||||
* @param datalen length of message to hash
|
||||
*/
|
||||
int tc_sha256_update (TCSha256State_t s, const uint8_t *data, size_t datalen);
|
||||
|
||||
/**
|
||||
* @brief SHA256 final procedure
|
||||
* Inserts the completed hash computation into digest
|
||||
* @return returns TC_CRYPTO_SUCCESS (1)
|
||||
* returns TC_CRYPTO_FAIL (0) if:
|
||||
* s == NULL,
|
||||
* s->iv == NULL,
|
||||
* digest == NULL
|
||||
* @note Assumes: s has been initialized by tc_sha256_init
|
||||
* digest points to at least TC_SHA256_DIGEST_SIZE bytes
|
||||
* @warning The state buffer 'leftover' is left in memory after processing
|
||||
* If your application intends to have sensitive data in this
|
||||
* buffer, remind to erase it after the data has been processed
|
||||
* @param digest unsigned eight bit integer
|
||||
* @param Sha256 state struct
|
||||
*/
|
||||
int tc_sha256_final(uint8_t *digest, TCSha256State_t s);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __TC_SHA256_H__ */
|
||||
@@ -0,0 +1,95 @@
|
||||
/* utils.h - TinyCrypt interface to platform-dependent run-time operations */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Interface to platform-dependent run-time operations.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __TC_UTILS_H__
|
||||
#define __TC_UTILS_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Copy the the buffer 'from' to the buffer 'to'.
|
||||
* @return returns TC_CRYPTO_SUCCESS (1)
|
||||
* returns TC_CRYPTO_FAIL (0) if:
|
||||
* from_len > to_len.
|
||||
*
|
||||
* @param to OUT -- destination buffer
|
||||
* @param to_len IN -- length of destination buffer
|
||||
* @param from IN -- origin buffer
|
||||
* @param from_len IN -- length of origin buffer
|
||||
*/
|
||||
unsigned int _copy(uint8_t *to, unsigned int to_len,
|
||||
const uint8_t *from, unsigned int from_len);
|
||||
|
||||
/**
|
||||
* @brief Set the value 'val' into the buffer 'to', 'len' times.
|
||||
*
|
||||
* @param to OUT -- destination buffer
|
||||
* @param val IN -- value to be set in 'to'
|
||||
* @param len IN -- number of times the value will be copied
|
||||
*/
|
||||
void _set(void *to, uint8_t val, unsigned int len);
|
||||
|
||||
/*
|
||||
* @brief AES specific doubling function, which utilizes
|
||||
* the finite field used by AES.
|
||||
* @return Returns a^2
|
||||
*
|
||||
* @param a IN/OUT -- value to be doubled
|
||||
*/
|
||||
uint8_t _double_byte(uint8_t a);
|
||||
|
||||
/*
|
||||
* @brief Constant-time algorithm to compare if two sequences of bytes are equal
|
||||
* @return Returns 0 if equal, and non-zero otherwise
|
||||
*
|
||||
* @param a IN -- sequence of bytes a
|
||||
* @param b IN -- sequence of bytes b
|
||||
* @param size IN -- size of sequences a and b
|
||||
*/
|
||||
int _compare(const uint8_t *a, const uint8_t *b, size_t size);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __TC_UTILS_H__ */
|
||||
164
lib/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/aes_decrypt.c
Normal file
164
lib/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/aes_decrypt.c
Normal file
@@ -0,0 +1,164 @@
|
||||
/* aes_decrypt.c - TinyCrypt implementation of AES decryption procedure */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "../include/tinycrypt/aes.h"
|
||||
#include "../include/tinycrypt/constants.h"
|
||||
#include "../include/tinycrypt/utils.h"
|
||||
|
||||
static const uint8_t inv_sbox[256] = {
|
||||
0x52, 0x09, 0x6a, 0xd5, 0x30, 0x36, 0xa5, 0x38, 0xbf, 0x40, 0xa3, 0x9e,
|
||||
0x81, 0xf3, 0xd7, 0xfb, 0x7c, 0xe3, 0x39, 0x82, 0x9b, 0x2f, 0xff, 0x87,
|
||||
0x34, 0x8e, 0x43, 0x44, 0xc4, 0xde, 0xe9, 0xcb, 0x54, 0x7b, 0x94, 0x32,
|
||||
0xa6, 0xc2, 0x23, 0x3d, 0xee, 0x4c, 0x95, 0x0b, 0x42, 0xfa, 0xc3, 0x4e,
|
||||
0x08, 0x2e, 0xa1, 0x66, 0x28, 0xd9, 0x24, 0xb2, 0x76, 0x5b, 0xa2, 0x49,
|
||||
0x6d, 0x8b, 0xd1, 0x25, 0x72, 0xf8, 0xf6, 0x64, 0x86, 0x68, 0x98, 0x16,
|
||||
0xd4, 0xa4, 0x5c, 0xcc, 0x5d, 0x65, 0xb6, 0x92, 0x6c, 0x70, 0x48, 0x50,
|
||||
0xfd, 0xed, 0xb9, 0xda, 0x5e, 0x15, 0x46, 0x57, 0xa7, 0x8d, 0x9d, 0x84,
|
||||
0x90, 0xd8, 0xab, 0x00, 0x8c, 0xbc, 0xd3, 0x0a, 0xf7, 0xe4, 0x58, 0x05,
|
||||
0xb8, 0xb3, 0x45, 0x06, 0xd0, 0x2c, 0x1e, 0x8f, 0xca, 0x3f, 0x0f, 0x02,
|
||||
0xc1, 0xaf, 0xbd, 0x03, 0x01, 0x13, 0x8a, 0x6b, 0x3a, 0x91, 0x11, 0x41,
|
||||
0x4f, 0x67, 0xdc, 0xea, 0x97, 0xf2, 0xcf, 0xce, 0xf0, 0xb4, 0xe6, 0x73,
|
||||
0x96, 0xac, 0x74, 0x22, 0xe7, 0xad, 0x35, 0x85, 0xe2, 0xf9, 0x37, 0xe8,
|
||||
0x1c, 0x75, 0xdf, 0x6e, 0x47, 0xf1, 0x1a, 0x71, 0x1d, 0x29, 0xc5, 0x89,
|
||||
0x6f, 0xb7, 0x62, 0x0e, 0xaa, 0x18, 0xbe, 0x1b, 0xfc, 0x56, 0x3e, 0x4b,
|
||||
0xc6, 0xd2, 0x79, 0x20, 0x9a, 0xdb, 0xc0, 0xfe, 0x78, 0xcd, 0x5a, 0xf4,
|
||||
0x1f, 0xdd, 0xa8, 0x33, 0x88, 0x07, 0xc7, 0x31, 0xb1, 0x12, 0x10, 0x59,
|
||||
0x27, 0x80, 0xec, 0x5f, 0x60, 0x51, 0x7f, 0xa9, 0x19, 0xb5, 0x4a, 0x0d,
|
||||
0x2d, 0xe5, 0x7a, 0x9f, 0x93, 0xc9, 0x9c, 0xef, 0xa0, 0xe0, 0x3b, 0x4d,
|
||||
0xae, 0x2a, 0xf5, 0xb0, 0xc8, 0xeb, 0xbb, 0x3c, 0x83, 0x53, 0x99, 0x61,
|
||||
0x17, 0x2b, 0x04, 0x7e, 0xba, 0x77, 0xd6, 0x26, 0xe1, 0x69, 0x14, 0x63,
|
||||
0x55, 0x21, 0x0c, 0x7d
|
||||
};
|
||||
|
||||
int tc_aes128_set_decrypt_key(TCAesKeySched_t s, const uint8_t *k)
|
||||
{
|
||||
return tc_aes128_set_encrypt_key(s, k);
|
||||
}
|
||||
|
||||
#define mult8(a)(_double_byte(_double_byte(_double_byte(a))))
|
||||
#define mult9(a)(mult8(a)^(a))
|
||||
#define multb(a)(mult8(a)^_double_byte(a)^(a))
|
||||
#define multd(a)(mult8(a)^_double_byte(_double_byte(a))^(a))
|
||||
#define multe(a)(mult8(a)^_double_byte(_double_byte(a))^_double_byte(a))
|
||||
|
||||
static inline void mult_row_column(uint8_t *out, const uint8_t *in)
|
||||
{
|
||||
out[0] = multe(in[0]) ^ multb(in[1]) ^ multd(in[2]) ^ mult9(in[3]);
|
||||
out[1] = mult9(in[0]) ^ multe(in[1]) ^ multb(in[2]) ^ multd(in[3]);
|
||||
out[2] = multd(in[0]) ^ mult9(in[1]) ^ multe(in[2]) ^ multb(in[3]);
|
||||
out[3] = multb(in[0]) ^ multd(in[1]) ^ mult9(in[2]) ^ multe(in[3]);
|
||||
}
|
||||
|
||||
static inline void inv_mix_columns(uint8_t *s)
|
||||
{
|
||||
uint8_t t[Nb*Nk];
|
||||
|
||||
mult_row_column(t, s);
|
||||
mult_row_column(&t[Nb], s+Nb);
|
||||
mult_row_column(&t[2*Nb], s+(2*Nb));
|
||||
mult_row_column(&t[3*Nb], s+(3*Nb));
|
||||
(void)_copy(s, sizeof(t), t, sizeof(t));
|
||||
}
|
||||
|
||||
static inline void add_round_key(uint8_t *s, const unsigned int *k)
|
||||
{
|
||||
s[0] ^= (uint8_t)(k[0] >> 24); s[1] ^= (uint8_t)(k[0] >> 16);
|
||||
s[2] ^= (uint8_t)(k[0] >> 8); s[3] ^= (uint8_t)(k[0]);
|
||||
s[4] ^= (uint8_t)(k[1] >> 24); s[5] ^= (uint8_t)(k[1] >> 16);
|
||||
s[6] ^= (uint8_t)(k[1] >> 8); s[7] ^= (uint8_t)(k[1]);
|
||||
s[8] ^= (uint8_t)(k[2] >> 24); s[9] ^= (uint8_t)(k[2] >> 16);
|
||||
s[10] ^= (uint8_t)(k[2] >> 8); s[11] ^= (uint8_t)(k[2]);
|
||||
s[12] ^= (uint8_t)(k[3] >> 24); s[13] ^= (uint8_t)(k[3] >> 16);
|
||||
s[14] ^= (uint8_t)(k[3] >> 8); s[15] ^= (uint8_t)(k[3]);
|
||||
}
|
||||
|
||||
static inline void inv_sub_bytes(uint8_t *s)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < (Nb*Nk); ++i) {
|
||||
s[i] = inv_sbox[s[i]];
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* This inv_shift_rows also implements the matrix flip required for
|
||||
* inv_mix_columns, but performs it here to reduce the number of memory
|
||||
* operations.
|
||||
*/
|
||||
static inline void inv_shift_rows(uint8_t *s)
|
||||
{
|
||||
uint8_t t[Nb*Nk];
|
||||
|
||||
t[0] = s[0]; t[1] = s[13]; t[2] = s[10]; t[3] = s[7];
|
||||
t[4] = s[4]; t[5] = s[1]; t[6] = s[14]; t[7] = s[11];
|
||||
t[8] = s[8]; t[9] = s[5]; t[10] = s[2]; t[11] = s[15];
|
||||
t[12] = s[12]; t[13] = s[9]; t[14] = s[6]; t[15] = s[3];
|
||||
(void)_copy(s, sizeof(t), t, sizeof(t));
|
||||
}
|
||||
|
||||
int tc_aes_decrypt(uint8_t *out, const uint8_t *in, const TCAesKeySched_t s)
|
||||
{
|
||||
uint8_t state[Nk*Nb];
|
||||
unsigned int i;
|
||||
|
||||
if (out == (uint8_t *) 0) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
} else if (in == (const uint8_t *) 0) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
} else if (s == (TCAesKeySched_t) 0) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
|
||||
(void)_copy(state, sizeof(state), in, sizeof(state));
|
||||
|
||||
add_round_key(state, s->words + Nb*Nr);
|
||||
|
||||
for (i = Nr - 1; i > 0; --i) {
|
||||
inv_shift_rows(state);
|
||||
inv_sub_bytes(state);
|
||||
add_round_key(state, s->words + Nb*i);
|
||||
inv_mix_columns(state);
|
||||
}
|
||||
|
||||
inv_shift_rows(state);
|
||||
inv_sub_bytes(state);
|
||||
add_round_key(state, s->words);
|
||||
|
||||
(void)_copy(out, sizeof(state), state, sizeof(state));
|
||||
|
||||
/*zeroing out the state buffer */
|
||||
_set(state, TC_ZERO_BYTE, sizeof(state));
|
||||
|
||||
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
191
lib/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/aes_encrypt.c
Normal file
191
lib/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/aes_encrypt.c
Normal file
@@ -0,0 +1,191 @@
|
||||
/* aes_encrypt.c - TinyCrypt implementation of AES encryption procedure */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "../include/tinycrypt/aes.h"
|
||||
#include "../include/tinycrypt/utils.h"
|
||||
#include "../include/tinycrypt/constants.h"
|
||||
|
||||
static const uint8_t sbox[256] = {
|
||||
0x63, 0x7c, 0x77, 0x7b, 0xf2, 0x6b, 0x6f, 0xc5, 0x30, 0x01, 0x67, 0x2b,
|
||||
0xfe, 0xd7, 0xab, 0x76, 0xca, 0x82, 0xc9, 0x7d, 0xfa, 0x59, 0x47, 0xf0,
|
||||
0xad, 0xd4, 0xa2, 0xaf, 0x9c, 0xa4, 0x72, 0xc0, 0xb7, 0xfd, 0x93, 0x26,
|
||||
0x36, 0x3f, 0xf7, 0xcc, 0x34, 0xa5, 0xe5, 0xf1, 0x71, 0xd8, 0x31, 0x15,
|
||||
0x04, 0xc7, 0x23, 0xc3, 0x18, 0x96, 0x05, 0x9a, 0x07, 0x12, 0x80, 0xe2,
|
||||
0xeb, 0x27, 0xb2, 0x75, 0x09, 0x83, 0x2c, 0x1a, 0x1b, 0x6e, 0x5a, 0xa0,
|
||||
0x52, 0x3b, 0xd6, 0xb3, 0x29, 0xe3, 0x2f, 0x84, 0x53, 0xd1, 0x00, 0xed,
|
||||
0x20, 0xfc, 0xb1, 0x5b, 0x6a, 0xcb, 0xbe, 0x39, 0x4a, 0x4c, 0x58, 0xcf,
|
||||
0xd0, 0xef, 0xaa, 0xfb, 0x43, 0x4d, 0x33, 0x85, 0x45, 0xf9, 0x02, 0x7f,
|
||||
0x50, 0x3c, 0x9f, 0xa8, 0x51, 0xa3, 0x40, 0x8f, 0x92, 0x9d, 0x38, 0xf5,
|
||||
0xbc, 0xb6, 0xda, 0x21, 0x10, 0xff, 0xf3, 0xd2, 0xcd, 0x0c, 0x13, 0xec,
|
||||
0x5f, 0x97, 0x44, 0x17, 0xc4, 0xa7, 0x7e, 0x3d, 0x64, 0x5d, 0x19, 0x73,
|
||||
0x60, 0x81, 0x4f, 0xdc, 0x22, 0x2a, 0x90, 0x88, 0x46, 0xee, 0xb8, 0x14,
|
||||
0xde, 0x5e, 0x0b, 0xdb, 0xe0, 0x32, 0x3a, 0x0a, 0x49, 0x06, 0x24, 0x5c,
|
||||
0xc2, 0xd3, 0xac, 0x62, 0x91, 0x95, 0xe4, 0x79, 0xe7, 0xc8, 0x37, 0x6d,
|
||||
0x8d, 0xd5, 0x4e, 0xa9, 0x6c, 0x56, 0xf4, 0xea, 0x65, 0x7a, 0xae, 0x08,
|
||||
0xba, 0x78, 0x25, 0x2e, 0x1c, 0xa6, 0xb4, 0xc6, 0xe8, 0xdd, 0x74, 0x1f,
|
||||
0x4b, 0xbd, 0x8b, 0x8a, 0x70, 0x3e, 0xb5, 0x66, 0x48, 0x03, 0xf6, 0x0e,
|
||||
0x61, 0x35, 0x57, 0xb9, 0x86, 0xc1, 0x1d, 0x9e, 0xe1, 0xf8, 0x98, 0x11,
|
||||
0x69, 0xd9, 0x8e, 0x94, 0x9b, 0x1e, 0x87, 0xe9, 0xce, 0x55, 0x28, 0xdf,
|
||||
0x8c, 0xa1, 0x89, 0x0d, 0xbf, 0xe6, 0x42, 0x68, 0x41, 0x99, 0x2d, 0x0f,
|
||||
0xb0, 0x54, 0xbb, 0x16
|
||||
};
|
||||
|
||||
static inline unsigned int rotword(unsigned int a)
|
||||
{
|
||||
return (((a) >> 24)|((a) << 8));
|
||||
}
|
||||
|
||||
#define subbyte(a, o)(sbox[((a) >> (o))&0xff] << (o))
|
||||
#define subword(a)(subbyte(a, 24)|subbyte(a, 16)|subbyte(a, 8)|subbyte(a, 0))
|
||||
|
||||
int tc_aes128_set_encrypt_key(TCAesKeySched_t s, const uint8_t *k)
|
||||
{
|
||||
const unsigned int rconst[11] = {
|
||||
0x00000000, 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000,
|
||||
0x20000000, 0x40000000, 0x80000000, 0x1b000000, 0x36000000
|
||||
};
|
||||
unsigned int i;
|
||||
unsigned int t;
|
||||
|
||||
if (s == (TCAesKeySched_t) 0) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
} else if (k == (const uint8_t *) 0) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
|
||||
for (i = 0; i < Nk; ++i) {
|
||||
s->words[i] = (k[Nb*i]<<24) | (k[Nb*i+1]<<16) |
|
||||
(k[Nb*i+2]<<8) | (k[Nb*i+3]);
|
||||
}
|
||||
|
||||
for (; i < (Nb * (Nr + 1)); ++i) {
|
||||
t = s->words[i-1];
|
||||
if ((i % Nk) == 0) {
|
||||
t = subword(rotword(t)) ^ rconst[i/Nk];
|
||||
}
|
||||
s->words[i] = s->words[i-Nk] ^ t;
|
||||
}
|
||||
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
|
||||
static inline void add_round_key(uint8_t *s, const unsigned int *k)
|
||||
{
|
||||
s[0] ^= (uint8_t)(k[0] >> 24); s[1] ^= (uint8_t)(k[0] >> 16);
|
||||
s[2] ^= (uint8_t)(k[0] >> 8); s[3] ^= (uint8_t)(k[0]);
|
||||
s[4] ^= (uint8_t)(k[1] >> 24); s[5] ^= (uint8_t)(k[1] >> 16);
|
||||
s[6] ^= (uint8_t)(k[1] >> 8); s[7] ^= (uint8_t)(k[1]);
|
||||
s[8] ^= (uint8_t)(k[2] >> 24); s[9] ^= (uint8_t)(k[2] >> 16);
|
||||
s[10] ^= (uint8_t)(k[2] >> 8); s[11] ^= (uint8_t)(k[2]);
|
||||
s[12] ^= (uint8_t)(k[3] >> 24); s[13] ^= (uint8_t)(k[3] >> 16);
|
||||
s[14] ^= (uint8_t)(k[3] >> 8); s[15] ^= (uint8_t)(k[3]);
|
||||
}
|
||||
|
||||
static inline void sub_bytes(uint8_t *s)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < (Nb * Nk); ++i) {
|
||||
s[i] = sbox[s[i]];
|
||||
}
|
||||
}
|
||||
|
||||
#define triple(a)(_double_byte(a)^(a))
|
||||
|
||||
static inline void mult_row_column(uint8_t *out, const uint8_t *in)
|
||||
{
|
||||
out[0] = _double_byte(in[0]) ^ triple(in[1]) ^ in[2] ^ in[3];
|
||||
out[1] = in[0] ^ _double_byte(in[1]) ^ triple(in[2]) ^ in[3];
|
||||
out[2] = in[0] ^ in[1] ^ _double_byte(in[2]) ^ triple(in[3]);
|
||||
out[3] = triple(in[0]) ^ in[1] ^ in[2] ^ _double_byte(in[3]);
|
||||
}
|
||||
|
||||
static inline void mix_columns(uint8_t *s)
|
||||
{
|
||||
uint8_t t[Nb*Nk];
|
||||
|
||||
mult_row_column(t, s);
|
||||
mult_row_column(&t[Nb], s+Nb);
|
||||
mult_row_column(&t[2 * Nb], s + (2 * Nb));
|
||||
mult_row_column(&t[3 * Nb], s + (3 * Nb));
|
||||
(void) _copy(s, sizeof(t), t, sizeof(t));
|
||||
}
|
||||
|
||||
/*
|
||||
* This shift_rows also implements the matrix flip required for mix_columns, but
|
||||
* performs it here to reduce the number of memory operations.
|
||||
*/
|
||||
static inline void shift_rows(uint8_t *s)
|
||||
{
|
||||
uint8_t t[Nb * Nk];
|
||||
|
||||
t[0] = s[0]; t[1] = s[5]; t[2] = s[10]; t[3] = s[15];
|
||||
t[4] = s[4]; t[5] = s[9]; t[6] = s[14]; t[7] = s[3];
|
||||
t[8] = s[8]; t[9] = s[13]; t[10] = s[2]; t[11] = s[7];
|
||||
t[12] = s[12]; t[13] = s[1]; t[14] = s[6]; t[15] = s[11];
|
||||
(void) _copy(s, sizeof(t), t, sizeof(t));
|
||||
}
|
||||
|
||||
int tc_aes_encrypt(uint8_t *out, const uint8_t *in, const TCAesKeySched_t s)
|
||||
{
|
||||
uint8_t state[Nk*Nb];
|
||||
unsigned int i;
|
||||
|
||||
if (out == (uint8_t *) 0) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
} else if (in == (const uint8_t *) 0) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
} else if (s == (TCAesKeySched_t) 0) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
|
||||
(void)_copy(state, sizeof(state), in, sizeof(state));
|
||||
add_round_key(state, s->words);
|
||||
|
||||
for (i = 0; i < (Nr - 1); ++i) {
|
||||
sub_bytes(state);
|
||||
shift_rows(state);
|
||||
mix_columns(state);
|
||||
add_round_key(state, s->words + Nb*(i+1));
|
||||
}
|
||||
|
||||
sub_bytes(state);
|
||||
shift_rows(state);
|
||||
add_round_key(state, s->words + Nb*(i+1));
|
||||
|
||||
(void)_copy(out, sizeof(state), state, sizeof(state));
|
||||
|
||||
/* zeroing out the state buffer */
|
||||
_set(state, TC_ZERO_BYTE, sizeof(state));
|
||||
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
114
lib/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/cbc_mode.c
Normal file
114
lib/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/cbc_mode.c
Normal file
@@ -0,0 +1,114 @@
|
||||
/* cbc_mode.c - TinyCrypt implementation of CBC mode encryption & decryption */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "../include/tinycrypt/cbc_mode.h"
|
||||
#include "../include/tinycrypt/constants.h"
|
||||
#include "../include/tinycrypt/utils.h"
|
||||
|
||||
int tc_cbc_mode_encrypt(uint8_t *out, unsigned int outlen, const uint8_t *in,
|
||||
unsigned int inlen, const uint8_t *iv,
|
||||
const TCAesKeySched_t sched)
|
||||
{
|
||||
|
||||
uint8_t buffer[TC_AES_BLOCK_SIZE];
|
||||
unsigned int n, m;
|
||||
|
||||
/* input sanity check: */
|
||||
if (out == (uint8_t *) 0 ||
|
||||
in == (const uint8_t *) 0 ||
|
||||
sched == (TCAesKeySched_t) 0 ||
|
||||
inlen == 0 ||
|
||||
outlen == 0 ||
|
||||
(inlen % TC_AES_BLOCK_SIZE) != 0 ||
|
||||
(outlen % TC_AES_BLOCK_SIZE) != 0 ||
|
||||
outlen != inlen + TC_AES_BLOCK_SIZE) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
|
||||
/* copy iv to the buffer */
|
||||
(void)_copy(buffer, TC_AES_BLOCK_SIZE, iv, TC_AES_BLOCK_SIZE);
|
||||
/* copy iv to the output buffer */
|
||||
(void)_copy(out, TC_AES_BLOCK_SIZE, iv, TC_AES_BLOCK_SIZE);
|
||||
out += TC_AES_BLOCK_SIZE;
|
||||
|
||||
for (n = m = 0; n < inlen; ++n) {
|
||||
buffer[m++] ^= *in++;
|
||||
if (m == TC_AES_BLOCK_SIZE) {
|
||||
(void)tc_aes_encrypt(buffer, buffer, sched);
|
||||
(void)_copy(out, TC_AES_BLOCK_SIZE,
|
||||
buffer, TC_AES_BLOCK_SIZE);
|
||||
out += TC_AES_BLOCK_SIZE;
|
||||
m = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
|
||||
int tc_cbc_mode_decrypt(uint8_t *out, unsigned int outlen, const uint8_t *in,
|
||||
unsigned int inlen, const uint8_t *iv,
|
||||
const TCAesKeySched_t sched)
|
||||
{
|
||||
|
||||
uint8_t buffer[TC_AES_BLOCK_SIZE];
|
||||
const uint8_t *p;
|
||||
unsigned int n, m;
|
||||
|
||||
/* sanity check the inputs */
|
||||
if (out == (uint8_t *) 0 ||
|
||||
in == (const uint8_t *) 0 ||
|
||||
sched == (TCAesKeySched_t) 0 ||
|
||||
inlen == 0 ||
|
||||
outlen == 0 ||
|
||||
(inlen % TC_AES_BLOCK_SIZE) != 0 ||
|
||||
(outlen % TC_AES_BLOCK_SIZE) != 0 ||
|
||||
outlen != inlen - TC_AES_BLOCK_SIZE) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Note that in == iv + ciphertext, i.e. the iv and the ciphertext are
|
||||
* contiguous. This allows for a very efficient decryption algorithm
|
||||
* that would not otherwise be possible.
|
||||
*/
|
||||
p = iv;
|
||||
for (n = m = 0; n < inlen; ++n) {
|
||||
if ((n % TC_AES_BLOCK_SIZE) == 0) {
|
||||
(void)tc_aes_decrypt(buffer, in, sched);
|
||||
in += TC_AES_BLOCK_SIZE;
|
||||
m = 0;
|
||||
}
|
||||
*out++ = buffer[m++] ^ *p++;
|
||||
}
|
||||
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
266
lib/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ccm_mode.c
Normal file
266
lib/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ccm_mode.c
Normal file
@@ -0,0 +1,266 @@
|
||||
/* ccm_mode.c - TinyCrypt implementation of CCM mode */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "../include/tinycrypt/ccm_mode.h"
|
||||
#include "../include/tinycrypt/constants.h"
|
||||
#include "../include/tinycrypt/utils.h"
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
int tc_ccm_config(TCCcmMode_t c, TCAesKeySched_t sched, uint8_t *nonce,
|
||||
unsigned int nlen, unsigned int mlen)
|
||||
{
|
||||
|
||||
/* input sanity check: */
|
||||
if (c == (TCCcmMode_t) 0 ||
|
||||
sched == (TCAesKeySched_t) 0 ||
|
||||
nonce == (uint8_t *) 0) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
} else if (nlen != 13) {
|
||||
return TC_CRYPTO_FAIL; /* The allowed nonce size is: 13. See documentation.*/
|
||||
} else if ((mlen < 4) || (mlen > 16) || (mlen & 1)) {
|
||||
return TC_CRYPTO_FAIL; /* The allowed mac sizes are: 4, 6, 8, 10, 12, 14, 16.*/
|
||||
}
|
||||
|
||||
c->mlen = mlen;
|
||||
c->sched = sched;
|
||||
c->nonce = nonce;
|
||||
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Variation of CBC-MAC mode used in CCM.
|
||||
*/
|
||||
static void ccm_cbc_mac(uint8_t *T, const uint8_t *data, unsigned int dlen,
|
||||
unsigned int flag, TCAesKeySched_t sched)
|
||||
{
|
||||
|
||||
unsigned int i;
|
||||
|
||||
if (flag > 0) {
|
||||
T[0] ^= (uint8_t)(dlen >> 8);
|
||||
T[1] ^= (uint8_t)(dlen);
|
||||
dlen += 2; i = 2;
|
||||
} else {
|
||||
i = 0;
|
||||
}
|
||||
|
||||
while (i < dlen) {
|
||||
T[i++ % (Nb * Nk)] ^= *data++;
|
||||
if (((i % (Nb * Nk)) == 0) || dlen == i) {
|
||||
(void) tc_aes_encrypt(T, T, sched);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Variation of CTR mode used in CCM.
|
||||
* The CTR mode used by CCM is slightly different than the conventional CTR
|
||||
* mode (the counter is increased before encryption, instead of after
|
||||
* encryption). Besides, it is assumed that the counter is stored in the last
|
||||
* 2 bytes of the nonce.
|
||||
*/
|
||||
static int ccm_ctr_mode(uint8_t *out, unsigned int outlen, const uint8_t *in,
|
||||
unsigned int inlen, uint8_t *ctr, const TCAesKeySched_t sched)
|
||||
{
|
||||
|
||||
uint8_t buffer[TC_AES_BLOCK_SIZE];
|
||||
uint8_t nonce[TC_AES_BLOCK_SIZE];
|
||||
uint16_t block_num;
|
||||
unsigned int i;
|
||||
|
||||
/* input sanity check: */
|
||||
if (out == (uint8_t *) 0 ||
|
||||
in == (uint8_t *) 0 ||
|
||||
ctr == (uint8_t *) 0 ||
|
||||
sched == (TCAesKeySched_t) 0 ||
|
||||
inlen == 0 ||
|
||||
outlen == 0 ||
|
||||
outlen != inlen) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
|
||||
/* copy the counter to the nonce */
|
||||
(void) _copy(nonce, sizeof(nonce), ctr, sizeof(nonce));
|
||||
|
||||
/* select the last 2 bytes of the nonce to be incremented */
|
||||
block_num = (uint16_t) ((nonce[14] << 8)|(nonce[15]));
|
||||
for (i = 0; i < inlen; ++i) {
|
||||
if ((i % (TC_AES_BLOCK_SIZE)) == 0) {
|
||||
block_num++;
|
||||
nonce[14] = (uint8_t)(block_num >> 8);
|
||||
nonce[15] = (uint8_t)(block_num);
|
||||
if (!tc_aes_encrypt(buffer, nonce, sched)) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
}
|
||||
/* update the output */
|
||||
*out++ = buffer[i % (TC_AES_BLOCK_SIZE)] ^ *in++;
|
||||
}
|
||||
|
||||
/* update the counter */
|
||||
ctr[14] = nonce[14]; ctr[15] = nonce[15];
|
||||
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
|
||||
int tc_ccm_generation_encryption(uint8_t *out, unsigned int olen,
|
||||
const uint8_t *associated_data,
|
||||
unsigned int alen, const uint8_t *payload,
|
||||
unsigned int plen, TCCcmMode_t c)
|
||||
{
|
||||
|
||||
/* input sanity check: */
|
||||
if ((out == (uint8_t *) 0) ||
|
||||
(c == (TCCcmMode_t) 0) ||
|
||||
((plen > 0) && (payload == (uint8_t *) 0)) ||
|
||||
((alen > 0) && (associated_data == (uint8_t *) 0)) ||
|
||||
(alen >= TC_CCM_AAD_MAX_BYTES) || /* associated data size unsupported */
|
||||
(plen >= TC_CCM_PAYLOAD_MAX_BYTES) || /* payload size unsupported */
|
||||
(olen < (plen + c->mlen))) { /* invalid output buffer size */
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
|
||||
uint8_t b[Nb * Nk];
|
||||
uint8_t tag[Nb * Nk];
|
||||
unsigned int i;
|
||||
|
||||
/* GENERATING THE AUTHENTICATION TAG: */
|
||||
|
||||
/* formatting the sequence b for authentication: */
|
||||
b[0] = ((alen > 0) ? 0x40:0) | (((c->mlen - 2) / 2 << 3)) | (1);
|
||||
for (i = 1; i <= 13; ++i) {
|
||||
b[i] = c->nonce[i - 1];
|
||||
}
|
||||
b[14] = (uint8_t)(plen >> 8);
|
||||
b[15] = (uint8_t)(plen);
|
||||
|
||||
/* computing the authentication tag using cbc-mac: */
|
||||
(void) tc_aes_encrypt(tag, b, c->sched);
|
||||
if (alen > 0) {
|
||||
ccm_cbc_mac(tag, associated_data, alen, 1, c->sched);
|
||||
}
|
||||
if (plen > 0) {
|
||||
ccm_cbc_mac(tag, payload, plen, 0, c->sched);
|
||||
}
|
||||
|
||||
/* ENCRYPTION: */
|
||||
|
||||
/* formatting the sequence b for encryption: */
|
||||
b[0] = 1; /* q - 1 = 2 - 1 = 1 */
|
||||
b[14] = b[15] = TC_ZERO_BYTE;
|
||||
|
||||
/* encrypting payload using ctr mode: */
|
||||
ccm_ctr_mode(out, plen, payload, plen, b, c->sched);
|
||||
|
||||
b[14] = b[15] = TC_ZERO_BYTE; /* restoring initial counter for ctr_mode (0):*/
|
||||
|
||||
/* encrypting b and adding the tag to the output: */
|
||||
(void) tc_aes_encrypt(b, b, c->sched);
|
||||
out += plen;
|
||||
for (i = 0; i < c->mlen; ++i) {
|
||||
*out++ = tag[i] ^ b[i];
|
||||
}
|
||||
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
|
||||
int tc_ccm_decryption_verification(uint8_t *out, unsigned int olen,
|
||||
const uint8_t *associated_data,
|
||||
unsigned int alen, const uint8_t *payload,
|
||||
unsigned int plen, TCCcmMode_t c)
|
||||
{
|
||||
|
||||
/* input sanity check: */
|
||||
if ((out == (uint8_t *) 0) ||
|
||||
(c == (TCCcmMode_t) 0) ||
|
||||
((plen > 0) && (payload == (uint8_t *) 0)) ||
|
||||
((alen > 0) && (associated_data == (uint8_t *) 0)) ||
|
||||
(alen >= TC_CCM_AAD_MAX_BYTES) || /* associated data size unsupported */
|
||||
(plen >= TC_CCM_PAYLOAD_MAX_BYTES) || /* payload size unsupported */
|
||||
(olen < plen - c->mlen)) { /* invalid output buffer size */
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
|
||||
uint8_t b[Nb * Nk];
|
||||
uint8_t tag[Nb * Nk];
|
||||
unsigned int i;
|
||||
|
||||
/* DECRYPTION: */
|
||||
|
||||
/* formatting the sequence b for decryption: */
|
||||
b[0] = 1; /* q - 1 = 2 - 1 = 1 */
|
||||
for (i = 1; i < 14; ++i) {
|
||||
b[i] = c->nonce[i - 1];
|
||||
}
|
||||
b[14] = b[15] = TC_ZERO_BYTE; /* initial counter value is 0 */
|
||||
|
||||
/* decrypting payload using ctr mode: */
|
||||
ccm_ctr_mode(out, plen - c->mlen, payload, plen - c->mlen, b, c->sched);
|
||||
|
||||
b[14] = b[15] = TC_ZERO_BYTE; /* restoring initial counter value (0) */
|
||||
|
||||
/* encrypting b and restoring the tag from input: */
|
||||
(void) tc_aes_encrypt(b, b, c->sched);
|
||||
for (i = 0; i < c->mlen; ++i) {
|
||||
tag[i] = *(payload + plen - c->mlen + i) ^ b[i];
|
||||
}
|
||||
|
||||
/* VERIFYING THE AUTHENTICATION TAG: */
|
||||
|
||||
/* formatting the sequence b for authentication: */
|
||||
b[0] = ((alen > 0) ? 0x40:0)|(((c->mlen - 2) / 2 << 3)) | (1);
|
||||
for (i = 1; i < 14; ++i) {
|
||||
b[i] = c->nonce[i - 1];
|
||||
}
|
||||
b[14] = (uint8_t)((plen - c->mlen) >> 8);
|
||||
b[15] = (uint8_t)(plen - c->mlen);
|
||||
|
||||
/* computing the authentication tag using cbc-mac: */
|
||||
(void) tc_aes_encrypt(b, b, c->sched);
|
||||
if (alen > 0) {
|
||||
ccm_cbc_mac(b, associated_data, alen, 1, c->sched);
|
||||
}
|
||||
if (plen > 0) {
|
||||
ccm_cbc_mac(b, out, plen - c->mlen, 0, c->sched);
|
||||
}
|
||||
|
||||
/* comparing the received tag and the computed one: */
|
||||
if (_compare(b, tag, c->mlen) == 0) {
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
} else {
|
||||
/* erase the decrypted buffer in case of mac validation failure: */
|
||||
_set(out, 0, plen - c->mlen);
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
}
|
||||
254
lib/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/cmac_mode.c
Normal file
254
lib/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/cmac_mode.c
Normal file
@@ -0,0 +1,254 @@
|
||||
/* cmac_mode.c - TinyCrypt CMAC mode implementation */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "../include/tinycrypt/aes.h"
|
||||
#include "../include/tinycrypt/cmac_mode.h"
|
||||
#include "../include/tinycrypt/constants.h"
|
||||
#include "../include/tinycrypt/utils.h"
|
||||
|
||||
/* max number of calls until change the key (2^48).*/
|
||||
const static uint64_t MAX_CALLS = ((uint64_t)1 << 48);
|
||||
|
||||
/*
|
||||
* gf_wrap -- In our implementation, GF(2^128) is represented as a 16 byte
|
||||
* array with byte 0 the most significant and byte 15 the least significant.
|
||||
* High bit carry reduction is based on the primitive polynomial
|
||||
*
|
||||
* X^128 + X^7 + X^2 + X + 1,
|
||||
*
|
||||
* which leads to the reduction formula X^128 = X^7 + X^2 + X + 1. Indeed,
|
||||
* since 0 = (X^128 + X^7 + X^2 + 1) mod (X^128 + X^7 + X^2 + X + 1) and since
|
||||
* addition of polynomials with coefficients in Z/Z(2) is just XOR, we can
|
||||
* add X^128 to both sides to get
|
||||
*
|
||||
* X^128 = (X^7 + X^2 + X + 1) mod (X^128 + X^7 + X^2 + X + 1)
|
||||
*
|
||||
* and the coefficients of the polynomial on the right hand side form the
|
||||
* string 1000 0111 = 0x87, which is the value of gf_wrap.
|
||||
*
|
||||
* This gets used in the following way. Doubling in GF(2^128) is just a left
|
||||
* shift by 1 bit, except when the most significant bit is 1. In the latter
|
||||
* case, the relation X^128 = X^7 + X^2 + X + 1 says that the high order bit
|
||||
* that overflows beyond 128 bits can be replaced by addition of
|
||||
* X^7 + X^2 + X + 1 <--> 0x87 to the low order 128 bits. Since addition
|
||||
* in GF(2^128) is represented by XOR, we therefore only have to XOR 0x87
|
||||
* into the low order byte after a left shift when the starting high order
|
||||
* bit is 1.
|
||||
*/
|
||||
const unsigned char gf_wrap = 0x87;
|
||||
|
||||
/*
|
||||
* assumes: out != NULL and points to a GF(2^n) value to receive the
|
||||
* doubled value;
|
||||
* in != NULL and points to a 16 byte GF(2^n) value
|
||||
* to double;
|
||||
* the in and out buffers do not overlap.
|
||||
* effects: doubles the GF(2^n) value pointed to by "in" and places
|
||||
* the result in the GF(2^n) value pointed to by "out."
|
||||
*/
|
||||
void gf_double(uint8_t *out, uint8_t *in)
|
||||
{
|
||||
|
||||
/* start with low order byte */
|
||||
uint8_t *x = in + (TC_AES_BLOCK_SIZE - 1);
|
||||
|
||||
/* if msb == 1, we need to add the gf_wrap value, otherwise add 0 */
|
||||
uint8_t carry = (in[0] >> 7) ? gf_wrap : 0;
|
||||
|
||||
out += (TC_AES_BLOCK_SIZE - 1);
|
||||
for (;;) {
|
||||
*out-- = (*x << 1) ^ carry;
|
||||
if (x == in) {
|
||||
break;
|
||||
}
|
||||
carry = *x-- >> 7;
|
||||
}
|
||||
}
|
||||
|
||||
int tc_cmac_setup(TCCmacState_t s, const uint8_t *key, TCAesKeySched_t sched)
|
||||
{
|
||||
|
||||
/* input sanity check: */
|
||||
if (s == (TCCmacState_t) 0 ||
|
||||
key == (const uint8_t *) 0) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
|
||||
/* put s into a known state */
|
||||
_set(s, 0, sizeof(*s));
|
||||
s->sched = sched;
|
||||
|
||||
/* configure the encryption key used by the underlying block cipher */
|
||||
tc_aes128_set_encrypt_key(s->sched, key);
|
||||
|
||||
/* compute s->K1 and s->K2 from s->iv using s->keyid */
|
||||
_set(s->iv, 0, TC_AES_BLOCK_SIZE);
|
||||
tc_aes_encrypt(s->iv, s->iv, s->sched);
|
||||
gf_double (s->K1, s->iv);
|
||||
gf_double (s->K2, s->K1);
|
||||
|
||||
/* reset s->iv to 0 in case someone wants to compute now */
|
||||
tc_cmac_init(s);
|
||||
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
|
||||
int tc_cmac_erase(TCCmacState_t s)
|
||||
{
|
||||
if (s == (TCCmacState_t) 0) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
|
||||
/* destroy the current state */
|
||||
_set(s, 0, sizeof(*s));
|
||||
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
|
||||
int tc_cmac_init(TCCmacState_t s)
|
||||
{
|
||||
/* input sanity check: */
|
||||
if (s == (TCCmacState_t) 0) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
|
||||
/* CMAC starts with an all zero initialization vector */
|
||||
_set(s->iv, 0, TC_AES_BLOCK_SIZE);
|
||||
|
||||
/* and the leftover buffer is empty */
|
||||
_set(s->leftover, 0, TC_AES_BLOCK_SIZE);
|
||||
s->leftover_offset = 0;
|
||||
|
||||
/* Set countdown to max number of calls allowed before re-keying: */
|
||||
s->countdown = MAX_CALLS;
|
||||
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
|
||||
int tc_cmac_update(TCCmacState_t s, const uint8_t *data, size_t data_length)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
/* input sanity check: */
|
||||
if (s == (TCCmacState_t) 0) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
if (data_length == 0) {
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
if (data == (const uint8_t *) 0) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
|
||||
if (s->countdown == 0) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
|
||||
s->countdown--;
|
||||
|
||||
if (s->leftover_offset > 0) {
|
||||
/* last data added to s didn't end on a TC_AES_BLOCK_SIZE byte boundary */
|
||||
size_t remaining_space = TC_AES_BLOCK_SIZE - s->leftover_offset;
|
||||
|
||||
if (data_length < remaining_space) {
|
||||
/* still not enough data to encrypt this time either */
|
||||
_copy(&s->leftover[s->leftover_offset], data_length, data, data_length);
|
||||
s->leftover_offset += data_length;
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
/* leftover block is now full; encrypt it first */
|
||||
_copy(&s->leftover[s->leftover_offset],
|
||||
remaining_space,
|
||||
data,
|
||||
remaining_space);
|
||||
data_length -= remaining_space;
|
||||
data += remaining_space;
|
||||
s->leftover_offset = 0;
|
||||
|
||||
for (i = 0; i < TC_AES_BLOCK_SIZE; ++i) {
|
||||
s->iv[i] ^= s->leftover[i];
|
||||
}
|
||||
tc_aes_encrypt(s->iv, s->iv, s->sched);
|
||||
}
|
||||
|
||||
/* CBC encrypt each (except the last) of the data blocks */
|
||||
while (data_length > TC_AES_BLOCK_SIZE) {
|
||||
for (i = 0; i < TC_AES_BLOCK_SIZE; ++i) {
|
||||
s->iv[i] ^= data[i];
|
||||
}
|
||||
tc_aes_encrypt(s->iv, s->iv, s->sched);
|
||||
data += TC_AES_BLOCK_SIZE;
|
||||
data_length -= TC_AES_BLOCK_SIZE;
|
||||
}
|
||||
|
||||
if (data_length > 0) {
|
||||
/* save leftover data for next time */
|
||||
_copy(s->leftover, data_length, data, data_length);
|
||||
s->leftover_offset = data_length;
|
||||
}
|
||||
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
|
||||
int tc_cmac_final(uint8_t *tag, TCCmacState_t s)
|
||||
{
|
||||
uint8_t *k;
|
||||
unsigned int i;
|
||||
|
||||
/* input sanity check: */
|
||||
if (tag == (uint8_t *) 0 ||
|
||||
s == (TCCmacState_t) 0) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
|
||||
if (s->leftover_offset == TC_AES_BLOCK_SIZE) {
|
||||
/* the last message block is a full-sized block */
|
||||
k = (uint8_t *) s->K1;
|
||||
} else {
|
||||
/* the final message block is not a full-sized block */
|
||||
size_t remaining = TC_AES_BLOCK_SIZE - s->leftover_offset;
|
||||
|
||||
_set(&s->leftover[s->leftover_offset], 0, remaining);
|
||||
s->leftover[s->leftover_offset] = TC_CMAC_PADDING;
|
||||
k = (uint8_t *) s->K2;
|
||||
}
|
||||
for (i = 0; i < TC_AES_BLOCK_SIZE; ++i) {
|
||||
s->iv[i] ^= s->leftover[i] ^ k[i];
|
||||
}
|
||||
|
||||
tc_aes_encrypt(tag, s->iv, s->sched);
|
||||
|
||||
/* erasing state: */
|
||||
tc_cmac_erase(s);
|
||||
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
85
lib/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ctr_mode.c
Normal file
85
lib/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ctr_mode.c
Normal file
@@ -0,0 +1,85 @@
|
||||
/* ctr_mode.c - TinyCrypt CTR mode implementation */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "../include/tinycrypt/constants.h"
|
||||
#include "../include/tinycrypt/ctr_mode.h"
|
||||
#include "../include/tinycrypt/utils.h"
|
||||
|
||||
int tc_ctr_mode(uint8_t *out, unsigned int outlen, const uint8_t *in,
|
||||
unsigned int inlen, uint8_t *ctr, const TCAesKeySched_t sched)
|
||||
{
|
||||
|
||||
uint8_t buffer[TC_AES_BLOCK_SIZE];
|
||||
uint8_t nonce[TC_AES_BLOCK_SIZE];
|
||||
unsigned int block_num;
|
||||
unsigned int i;
|
||||
|
||||
/* input sanity check: */
|
||||
if (out == (uint8_t *) 0 ||
|
||||
in == (uint8_t *) 0 ||
|
||||
ctr == (uint8_t *) 0 ||
|
||||
sched == (TCAesKeySched_t) 0 ||
|
||||
inlen == 0 ||
|
||||
outlen == 0 ||
|
||||
outlen != inlen) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
|
||||
/* copy the ctr to the nonce */
|
||||
(void)_copy(nonce, sizeof(nonce), ctr, sizeof(nonce));
|
||||
|
||||
/* select the last 4 bytes of the nonce to be incremented */
|
||||
block_num = (nonce[12] << 24) | (nonce[13] << 16) |
|
||||
(nonce[14] << 8) | (nonce[15]);
|
||||
for (i = 0; i < inlen; ++i) {
|
||||
if ((i % (TC_AES_BLOCK_SIZE)) == 0) {
|
||||
/* encrypt data using the current nonce */
|
||||
if (tc_aes_encrypt(buffer, nonce, sched)) {
|
||||
block_num++;
|
||||
nonce[12] = (uint8_t)(block_num >> 24);
|
||||
nonce[13] = (uint8_t)(block_num >> 16);
|
||||
nonce[14] = (uint8_t)(block_num >> 8);
|
||||
nonce[15] = (uint8_t)(block_num);
|
||||
} else {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
}
|
||||
/* update the output */
|
||||
*out++ = buffer[i%(TC_AES_BLOCK_SIZE)] ^ *in++;
|
||||
}
|
||||
|
||||
/* update the counter */
|
||||
ctr[12] = nonce[12]; ctr[13] = nonce[13];
|
||||
ctr[14] = nonce[14]; ctr[15] = nonce[15];
|
||||
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
283
lib/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ctr_prng.c
Normal file
283
lib/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ctr_prng.c
Normal file
@@ -0,0 +1,283 @@
|
||||
/* ctr_prng.c - TinyCrypt implementation of CTR-PRNG */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2016, Chris Morrison
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "../include/tinycrypt/ctr_prng.h"
|
||||
#include "../include/tinycrypt/utils.h"
|
||||
#include "../include/tinycrypt/constants.h"
|
||||
#include <string.h>
|
||||
|
||||
/*
|
||||
* This PRNG is based on the CTR_DRBG described in Recommendation for Random
|
||||
* Number Generation Using Deterministic Random Bit Generators,
|
||||
* NIST SP 800-90A Rev. 1.
|
||||
*
|
||||
* Annotations to particular steps (e.g. 10.2.1.2 Step 1) refer to the steps
|
||||
* described in that document.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Array incrementer
|
||||
* Treats the supplied array as one contiguous number (MSB in arr[0]), and
|
||||
* increments it by one
|
||||
* @return none
|
||||
* @param arr IN/OUT -- array to be incremented
|
||||
* @param len IN -- size of arr in bytes
|
||||
*/
|
||||
static void arrInc(uint8_t arr[], unsigned int len)
|
||||
{
|
||||
unsigned int i;
|
||||
if (0 != arr) {
|
||||
for (i = len; i > 0U; i--) {
|
||||
if (++arr[i-1] != 0U) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief CTR PRNG update
|
||||
* Updates the internal state of supplied the CTR PRNG context
|
||||
* increments it by one
|
||||
* @return none
|
||||
* @note Assumes: providedData is (TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE) bytes long
|
||||
* @param ctx IN/OUT -- CTR PRNG state
|
||||
* @param providedData IN -- data used when updating the internal state
|
||||
*/
|
||||
static void tc_ctr_prng_update(TCCtrPrng_t * const ctx, uint8_t const * const providedData)
|
||||
{
|
||||
if (0 != ctx) {
|
||||
/* 10.2.1.2 step 1 */
|
||||
uint8_t temp[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE];
|
||||
unsigned int len = 0U;
|
||||
|
||||
/* 10.2.1.2 step 2 */
|
||||
while (len < sizeof temp) {
|
||||
unsigned int blocklen = sizeof(temp) - len;
|
||||
uint8_t output_block[TC_AES_BLOCK_SIZE];
|
||||
|
||||
/* 10.2.1.2 step 2.1 */
|
||||
arrInc(ctx->V, sizeof ctx->V);
|
||||
|
||||
/* 10.2.1.2 step 2.2 */
|
||||
if (blocklen > TC_AES_BLOCK_SIZE) {
|
||||
blocklen = TC_AES_BLOCK_SIZE;
|
||||
}
|
||||
(void)tc_aes_encrypt(output_block, ctx->V, &ctx->key);
|
||||
|
||||
/* 10.2.1.2 step 2.3/step 3 */
|
||||
memcpy(&(temp[len]), output_block, blocklen);
|
||||
|
||||
len += blocklen;
|
||||
}
|
||||
|
||||
/* 10.2.1.2 step 4 */
|
||||
if (0 != providedData) {
|
||||
unsigned int i;
|
||||
for (i = 0U; i < sizeof temp; i++) {
|
||||
temp[i] ^= providedData[i];
|
||||
}
|
||||
}
|
||||
|
||||
/* 10.2.1.2 step 5 */
|
||||
(void)tc_aes128_set_encrypt_key(&ctx->key, temp);
|
||||
|
||||
/* 10.2.1.2 step 6 */
|
||||
memcpy(ctx->V, &(temp[TC_AES_KEY_SIZE]), TC_AES_BLOCK_SIZE);
|
||||
}
|
||||
}
|
||||
|
||||
int tc_ctr_prng_init(TCCtrPrng_t * const ctx,
|
||||
uint8_t const * const entropy,
|
||||
unsigned int entropyLen,
|
||||
uint8_t const * const personalization,
|
||||
unsigned int pLen)
|
||||
{
|
||||
int result = TC_CRYPTO_FAIL;
|
||||
unsigned int i;
|
||||
uint8_t personalization_buf[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE] = {0U};
|
||||
uint8_t seed_material[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE];
|
||||
uint8_t zeroArr[TC_AES_BLOCK_SIZE] = {0U};
|
||||
|
||||
if (0 != personalization) {
|
||||
/* 10.2.1.3.1 step 1 */
|
||||
unsigned int len = pLen;
|
||||
if (len > sizeof personalization_buf) {
|
||||
len = sizeof personalization_buf;
|
||||
}
|
||||
|
||||
/* 10.2.1.3.1 step 2 */
|
||||
memcpy(personalization_buf, personalization, len);
|
||||
}
|
||||
|
||||
if ((0 != ctx) && (0 != entropy) && (entropyLen >= sizeof seed_material)) {
|
||||
/* 10.2.1.3.1 step 3 */
|
||||
memcpy(seed_material, entropy, sizeof seed_material);
|
||||
for (i = 0U; i < sizeof seed_material; i++) {
|
||||
seed_material[i] ^= personalization_buf[i];
|
||||
}
|
||||
|
||||
/* 10.2.1.3.1 step 4 */
|
||||
(void)tc_aes128_set_encrypt_key(&ctx->key, zeroArr);
|
||||
|
||||
/* 10.2.1.3.1 step 5 */
|
||||
memset(ctx->V, 0x00, sizeof ctx->V);
|
||||
|
||||
/* 10.2.1.3.1 step 6 */
|
||||
tc_ctr_prng_update(ctx, seed_material);
|
||||
|
||||
/* 10.2.1.3.1 step 7 */
|
||||
ctx->reseedCount = 1U;
|
||||
|
||||
result = TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int tc_ctr_prng_reseed(TCCtrPrng_t * const ctx,
|
||||
uint8_t const * const entropy,
|
||||
unsigned int entropyLen,
|
||||
uint8_t const * const additional_input,
|
||||
unsigned int additionallen)
|
||||
{
|
||||
unsigned int i;
|
||||
int result = TC_CRYPTO_FAIL;
|
||||
uint8_t additional_input_buf[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE] = {0U};
|
||||
uint8_t seed_material[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE];
|
||||
|
||||
if (0 != additional_input) {
|
||||
/* 10.2.1.4.1 step 1 */
|
||||
unsigned int len = additionallen;
|
||||
if (len > sizeof additional_input_buf) {
|
||||
len = sizeof additional_input_buf;
|
||||
}
|
||||
|
||||
/* 10.2.1.4.1 step 2 */
|
||||
memcpy(additional_input_buf, additional_input, len);
|
||||
}
|
||||
|
||||
unsigned int seedlen = (unsigned int)TC_AES_KEY_SIZE + (unsigned int)TC_AES_BLOCK_SIZE;
|
||||
if ((0 != ctx) && (entropyLen >= seedlen)) {
|
||||
/* 10.2.1.4.1 step 3 */
|
||||
memcpy(seed_material, entropy, sizeof seed_material);
|
||||
for (i = 0U; i < sizeof seed_material; i++) {
|
||||
seed_material[i] ^= additional_input_buf[i];
|
||||
}
|
||||
|
||||
/* 10.2.1.4.1 step 4 */
|
||||
tc_ctr_prng_update(ctx, seed_material);
|
||||
|
||||
/* 10.2.1.4.1 step 5 */
|
||||
ctx->reseedCount = 1U;
|
||||
|
||||
result = TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int tc_ctr_prng_generate(TCCtrPrng_t * const ctx,
|
||||
uint8_t const * const additional_input,
|
||||
unsigned int additionallen,
|
||||
uint8_t * const out,
|
||||
unsigned int outlen)
|
||||
{
|
||||
/* 2^48 - see section 10.2.1 */
|
||||
static const uint64_t MAX_REQS_BEFORE_RESEED = 0x1000000000000ULL;
|
||||
|
||||
/* 2^19 bits - see section 10.2.1 */
|
||||
static const unsigned int MAX_BYTES_PER_REQ = 65536U;
|
||||
|
||||
unsigned int result = TC_CRYPTO_FAIL;
|
||||
|
||||
if ((0 != ctx) && (0 != out) && (outlen < MAX_BYTES_PER_REQ)) {
|
||||
/* 10.2.1.5.1 step 1 */
|
||||
if (ctx->reseedCount > MAX_REQS_BEFORE_RESEED) {
|
||||
result = TC_CTR_PRNG_RESEED_REQ;
|
||||
} else {
|
||||
uint8_t additional_input_buf[TC_AES_KEY_SIZE + TC_AES_BLOCK_SIZE] = {0U};
|
||||
if (0 != additional_input) {
|
||||
/* 10.2.1.5.1 step 2 */
|
||||
unsigned int len = additionallen;
|
||||
if (len > sizeof additional_input_buf) {
|
||||
len = sizeof additional_input_buf;
|
||||
}
|
||||
memcpy(additional_input_buf, additional_input, len);
|
||||
tc_ctr_prng_update(ctx, additional_input_buf);
|
||||
}
|
||||
|
||||
/* 10.2.1.5.1 step 3 - implicit */
|
||||
|
||||
/* 10.2.1.5.1 step 4 */
|
||||
unsigned int len = 0U;
|
||||
while (len < outlen) {
|
||||
unsigned int blocklen = outlen - len;
|
||||
uint8_t output_block[TC_AES_BLOCK_SIZE];
|
||||
|
||||
/* 10.2.1.5.1 step 4.1 */
|
||||
arrInc(ctx->V, sizeof ctx->V);
|
||||
|
||||
/* 10.2.1.5.1 step 4.2 */
|
||||
(void)tc_aes_encrypt(output_block, ctx->V, &ctx->key);
|
||||
|
||||
/* 10.2.1.5.1 step 4.3/step 5 */
|
||||
if (blocklen > TC_AES_BLOCK_SIZE) {
|
||||
blocklen = TC_AES_BLOCK_SIZE;
|
||||
}
|
||||
memcpy(&(out[len]), output_block, blocklen);
|
||||
|
||||
len += blocklen;
|
||||
}
|
||||
|
||||
/* 10.2.1.5.1 step 6 */
|
||||
tc_ctr_prng_update(ctx, additional_input_buf);
|
||||
|
||||
/* 10.2.1.5.1 step 7 */
|
||||
ctx->reseedCount++;
|
||||
|
||||
/* 10.2.1.5.1 step 8 */
|
||||
result = TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void tc_ctr_prng_uninstantiate(TCCtrPrng_t * const ctx)
|
||||
{
|
||||
if (0 != ctx) {
|
||||
memset(ctx->key.words, 0x00, sizeof ctx->key.words);
|
||||
memset(ctx->V, 0x00, sizeof ctx->V);
|
||||
ctx->reseedCount = 0U;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
942
lib/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ecc.c
Normal file
942
lib/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ecc.c
Normal file
@@ -0,0 +1,942 @@
|
||||
/* ecc.c - TinyCrypt implementation of common ECC functions */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2014, Kenneth MacKay
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "../include/tinycrypt/ecc.h"
|
||||
#include "../include/tinycrypt/ecc_platform_specific.h"
|
||||
#include <string.h>
|
||||
|
||||
/* IMPORTANT: Make sure a cryptographically-secure PRNG is set and the platform
|
||||
* has access to enough entropy in order to feed the PRNG regularly. */
|
||||
#if default_RNG_defined
|
||||
static uECC_RNG_Function g_rng_function = &default_CSPRNG;
|
||||
#else
|
||||
static uECC_RNG_Function g_rng_function = 0;
|
||||
#endif
|
||||
|
||||
void uECC_set_rng(uECC_RNG_Function rng_function)
|
||||
{
|
||||
g_rng_function = rng_function;
|
||||
}
|
||||
|
||||
uECC_RNG_Function uECC_get_rng(void)
|
||||
{
|
||||
return g_rng_function;
|
||||
}
|
||||
|
||||
int uECC_curve_private_key_size(uECC_Curve curve)
|
||||
{
|
||||
return BITS_TO_BYTES(curve->num_n_bits);
|
||||
}
|
||||
|
||||
int uECC_curve_public_key_size(uECC_Curve curve)
|
||||
{
|
||||
return 2 * curve->num_bytes;
|
||||
}
|
||||
|
||||
void uECC_vli_clear(uECC_word_t *vli, wordcount_t num_words)
|
||||
{
|
||||
wordcount_t i;
|
||||
for (i = 0; i < num_words; ++i) {
|
||||
vli[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
uECC_word_t uECC_vli_isZero(const uECC_word_t *vli, wordcount_t num_words)
|
||||
{
|
||||
uECC_word_t bits = 0;
|
||||
wordcount_t i;
|
||||
for (i = 0; i < num_words; ++i) {
|
||||
bits |= vli[i];
|
||||
}
|
||||
return (bits == 0);
|
||||
}
|
||||
|
||||
uECC_word_t uECC_vli_testBit(const uECC_word_t *vli, bitcount_t bit)
|
||||
{
|
||||
return (vli[bit >> uECC_WORD_BITS_SHIFT] &
|
||||
((uECC_word_t)1 << (bit & uECC_WORD_BITS_MASK)));
|
||||
}
|
||||
|
||||
/* Counts the number of words in vli. */
|
||||
static wordcount_t vli_numDigits(const uECC_word_t *vli,
|
||||
const wordcount_t max_words)
|
||||
{
|
||||
|
||||
wordcount_t i;
|
||||
/* Search from the end until we find a non-zero digit. We do it in reverse
|
||||
* because we expect that most digits will be nonzero. */
|
||||
for (i = max_words - 1; i >= 0 && vli[i] == 0; --i) {
|
||||
}
|
||||
|
||||
return (i + 1);
|
||||
}
|
||||
|
||||
bitcount_t uECC_vli_numBits(const uECC_word_t *vli,
|
||||
const wordcount_t max_words)
|
||||
{
|
||||
|
||||
uECC_word_t i;
|
||||
uECC_word_t digit;
|
||||
|
||||
wordcount_t num_digits = vli_numDigits(vli, max_words);
|
||||
if (num_digits == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
digit = vli[num_digits - 1];
|
||||
for (i = 0; digit; ++i) {
|
||||
digit >>= 1;
|
||||
}
|
||||
|
||||
return (((bitcount_t)(num_digits - 1) << uECC_WORD_BITS_SHIFT) + i);
|
||||
}
|
||||
|
||||
void uECC_vli_set(uECC_word_t *dest, const uECC_word_t *src,
|
||||
wordcount_t num_words)
|
||||
{
|
||||
wordcount_t i;
|
||||
|
||||
for (i = 0; i < num_words; ++i) {
|
||||
dest[i] = src[i];
|
||||
}
|
||||
}
|
||||
|
||||
cmpresult_t uECC_vli_cmp_unsafe(const uECC_word_t *left,
|
||||
const uECC_word_t *right,
|
||||
wordcount_t num_words)
|
||||
{
|
||||
wordcount_t i;
|
||||
|
||||
for (i = num_words - 1; i >= 0; --i) {
|
||||
if (left[i] > right[i]) {
|
||||
return 1;
|
||||
} else if (left[i] < right[i]) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
uECC_word_t uECC_vli_equal(const uECC_word_t *left, const uECC_word_t *right,
|
||||
wordcount_t num_words)
|
||||
{
|
||||
|
||||
uECC_word_t diff = 0;
|
||||
wordcount_t i;
|
||||
|
||||
for (i = num_words - 1; i >= 0; --i) {
|
||||
diff |= (left[i] ^ right[i]);
|
||||
}
|
||||
return !(diff == 0);
|
||||
}
|
||||
|
||||
uECC_word_t cond_set(uECC_word_t p_true, uECC_word_t p_false, unsigned int cond)
|
||||
{
|
||||
return (p_true*(cond)) | (p_false*(!cond));
|
||||
}
|
||||
|
||||
/* Computes result = left - right, returning borrow, in constant time.
|
||||
* Can modify in place. */
|
||||
uECC_word_t uECC_vli_sub(uECC_word_t *result, const uECC_word_t *left,
|
||||
const uECC_word_t *right, wordcount_t num_words)
|
||||
{
|
||||
uECC_word_t borrow = 0;
|
||||
wordcount_t i;
|
||||
for (i = 0; i < num_words; ++i) {
|
||||
uECC_word_t diff = left[i] - right[i] - borrow;
|
||||
uECC_word_t val = (diff > left[i]);
|
||||
borrow = cond_set(val, borrow, (diff != left[i]));
|
||||
|
||||
result[i] = diff;
|
||||
}
|
||||
return borrow;
|
||||
}
|
||||
|
||||
/* Computes result = left + right, returning carry, in constant time.
|
||||
* Can modify in place. */
|
||||
static uECC_word_t uECC_vli_add(uECC_word_t *result, const uECC_word_t *left,
|
||||
const uECC_word_t *right, wordcount_t num_words)
|
||||
{
|
||||
uECC_word_t carry = 0;
|
||||
wordcount_t i;
|
||||
for (i = 0; i < num_words; ++i) {
|
||||
uECC_word_t sum = left[i] + right[i] + carry;
|
||||
uECC_word_t val = (sum < left[i]);
|
||||
carry = cond_set(val, carry, (sum != left[i]));
|
||||
result[i] = sum;
|
||||
}
|
||||
return carry;
|
||||
}
|
||||
|
||||
cmpresult_t uECC_vli_cmp(const uECC_word_t *left, const uECC_word_t *right,
|
||||
wordcount_t num_words)
|
||||
{
|
||||
uECC_word_t tmp[NUM_ECC_WORDS];
|
||||
uECC_word_t neg = !!uECC_vli_sub(tmp, left, right, num_words);
|
||||
uECC_word_t equal = uECC_vli_isZero(tmp, num_words);
|
||||
return (!equal - 2 * neg);
|
||||
}
|
||||
|
||||
/* Computes vli = vli >> 1. */
|
||||
static void uECC_vli_rshift1(uECC_word_t *vli, wordcount_t num_words)
|
||||
{
|
||||
uECC_word_t *end = vli;
|
||||
uECC_word_t carry = 0;
|
||||
|
||||
vli += num_words;
|
||||
while (vli-- > end) {
|
||||
uECC_word_t temp = *vli;
|
||||
*vli = (temp >> 1) | carry;
|
||||
carry = temp << (uECC_WORD_BITS - 1);
|
||||
}
|
||||
}
|
||||
|
||||
static void muladd(uECC_word_t a, uECC_word_t b, uECC_word_t *r0,
|
||||
uECC_word_t *r1, uECC_word_t *r2)
|
||||
{
|
||||
|
||||
uECC_dword_t p = (uECC_dword_t)a * b;
|
||||
uECC_dword_t r01 = ((uECC_dword_t)(*r1) << uECC_WORD_BITS) | *r0;
|
||||
r01 += p;
|
||||
*r2 += (r01 < p);
|
||||
*r1 = r01 >> uECC_WORD_BITS;
|
||||
*r0 = (uECC_word_t)r01;
|
||||
|
||||
}
|
||||
|
||||
/* Computes result = left * right. Result must be 2 * num_words long. */
|
||||
static void uECC_vli_mult(uECC_word_t *result, const uECC_word_t *left,
|
||||
const uECC_word_t *right, wordcount_t num_words)
|
||||
{
|
||||
|
||||
uECC_word_t r0 = 0;
|
||||
uECC_word_t r1 = 0;
|
||||
uECC_word_t r2 = 0;
|
||||
wordcount_t i, k;
|
||||
|
||||
/* Compute each digit of result in sequence, maintaining the carries. */
|
||||
for (k = 0; k < num_words; ++k) {
|
||||
|
||||
for (i = 0; i <= k; ++i) {
|
||||
muladd(left[i], right[k - i], &r0, &r1, &r2);
|
||||
}
|
||||
|
||||
result[k] = r0;
|
||||
r0 = r1;
|
||||
r1 = r2;
|
||||
r2 = 0;
|
||||
}
|
||||
|
||||
for (k = num_words; k < num_words * 2 - 1; ++k) {
|
||||
|
||||
for (i = (k + 1) - num_words; i < num_words; ++i) {
|
||||
muladd(left[i], right[k - i], &r0, &r1, &r2);
|
||||
}
|
||||
result[k] = r0;
|
||||
r0 = r1;
|
||||
r1 = r2;
|
||||
r2 = 0;
|
||||
}
|
||||
result[num_words * 2 - 1] = r0;
|
||||
}
|
||||
|
||||
void uECC_vli_modAdd(uECC_word_t *result, const uECC_word_t *left,
|
||||
const uECC_word_t *right, const uECC_word_t *mod,
|
||||
wordcount_t num_words)
|
||||
{
|
||||
uECC_word_t carry = uECC_vli_add(result, left, right, num_words);
|
||||
if (carry || uECC_vli_cmp_unsafe(mod, result, num_words) != 1) {
|
||||
/* result > mod (result = mod + remainder), so subtract mod to get
|
||||
* remainder. */
|
||||
uECC_vli_sub(result, result, mod, num_words);
|
||||
}
|
||||
}
|
||||
|
||||
void uECC_vli_modSub(uECC_word_t *result, const uECC_word_t *left,
|
||||
const uECC_word_t *right, const uECC_word_t *mod,
|
||||
wordcount_t num_words)
|
||||
{
|
||||
uECC_word_t l_borrow = uECC_vli_sub(result, left, right, num_words);
|
||||
if (l_borrow) {
|
||||
/* In this case, result == -diff == (max int) - diff. Since -x % d == d - x,
|
||||
* we can get the correct result from result + mod (with overflow). */
|
||||
uECC_vli_add(result, result, mod, num_words);
|
||||
}
|
||||
}
|
||||
|
||||
/* Computes result = product % mod, where product is 2N words long. */
|
||||
/* Currently only designed to work for curve_p or curve_n. */
|
||||
void uECC_vli_mmod(uECC_word_t *result, uECC_word_t *product,
|
||||
const uECC_word_t *mod, wordcount_t num_words)
|
||||
{
|
||||
uECC_word_t mod_multiple[2 * NUM_ECC_WORDS];
|
||||
uECC_word_t tmp[2 * NUM_ECC_WORDS];
|
||||
uECC_word_t *v[2] = {tmp, product};
|
||||
uECC_word_t index;
|
||||
|
||||
/* Shift mod so its highest set bit is at the maximum position. */
|
||||
bitcount_t shift = (num_words * 2 * uECC_WORD_BITS) -
|
||||
uECC_vli_numBits(mod, num_words);
|
||||
wordcount_t word_shift = shift / uECC_WORD_BITS;
|
||||
wordcount_t bit_shift = shift % uECC_WORD_BITS;
|
||||
uECC_word_t carry = 0;
|
||||
uECC_vli_clear(mod_multiple, word_shift);
|
||||
if (bit_shift > 0) {
|
||||
for(index = 0; index < (uECC_word_t)num_words; ++index) {
|
||||
mod_multiple[word_shift + index] = (mod[index] << bit_shift) | carry;
|
||||
carry = mod[index] >> (uECC_WORD_BITS - bit_shift);
|
||||
}
|
||||
} else {
|
||||
uECC_vli_set(mod_multiple + word_shift, mod, num_words);
|
||||
}
|
||||
|
||||
for (index = 1; shift >= 0; --shift) {
|
||||
uECC_word_t borrow = 0;
|
||||
wordcount_t i;
|
||||
for (i = 0; i < num_words * 2; ++i) {
|
||||
uECC_word_t diff = v[index][i] - mod_multiple[i] - borrow;
|
||||
if (diff != v[index][i]) {
|
||||
borrow = (diff > v[index][i]);
|
||||
}
|
||||
v[1 - index][i] = diff;
|
||||
}
|
||||
/* Swap the index if there was no borrow */
|
||||
index = !(index ^ borrow);
|
||||
uECC_vli_rshift1(mod_multiple, num_words);
|
||||
mod_multiple[num_words - 1] |= mod_multiple[num_words] <<
|
||||
(uECC_WORD_BITS - 1);
|
||||
uECC_vli_rshift1(mod_multiple + num_words, num_words);
|
||||
}
|
||||
uECC_vli_set(result, v[index], num_words);
|
||||
}
|
||||
|
||||
void uECC_vli_modMult(uECC_word_t *result, const uECC_word_t *left,
|
||||
const uECC_word_t *right, const uECC_word_t *mod,
|
||||
wordcount_t num_words)
|
||||
{
|
||||
uECC_word_t product[2 * NUM_ECC_WORDS];
|
||||
uECC_vli_mult(product, left, right, num_words);
|
||||
uECC_vli_mmod(result, product, mod, num_words);
|
||||
}
|
||||
|
||||
void uECC_vli_modMult_fast(uECC_word_t *result, const uECC_word_t *left,
|
||||
const uECC_word_t *right, uECC_Curve curve)
|
||||
{
|
||||
uECC_word_t product[2 * NUM_ECC_WORDS];
|
||||
uECC_vli_mult(product, left, right, curve->num_words);
|
||||
|
||||
curve->mmod_fast(result, product);
|
||||
}
|
||||
|
||||
static void uECC_vli_modSquare_fast(uECC_word_t *result,
|
||||
const uECC_word_t *left,
|
||||
uECC_Curve curve)
|
||||
{
|
||||
uECC_vli_modMult_fast(result, left, left, curve);
|
||||
}
|
||||
|
||||
|
||||
#define EVEN(vli) (!(vli[0] & 1))
|
||||
|
||||
static void vli_modInv_update(uECC_word_t *uv,
|
||||
const uECC_word_t *mod,
|
||||
wordcount_t num_words)
|
||||
{
|
||||
|
||||
uECC_word_t carry = 0;
|
||||
|
||||
if (!EVEN(uv)) {
|
||||
carry = uECC_vli_add(uv, uv, mod, num_words);
|
||||
}
|
||||
uECC_vli_rshift1(uv, num_words);
|
||||
if (carry) {
|
||||
uv[num_words - 1] |= HIGH_BIT_SET;
|
||||
}
|
||||
}
|
||||
|
||||
void uECC_vli_modInv(uECC_word_t *result, const uECC_word_t *input,
|
||||
const uECC_word_t *mod, wordcount_t num_words)
|
||||
{
|
||||
uECC_word_t a[NUM_ECC_WORDS], b[NUM_ECC_WORDS];
|
||||
uECC_word_t u[NUM_ECC_WORDS], v[NUM_ECC_WORDS];
|
||||
cmpresult_t cmpResult;
|
||||
|
||||
if (uECC_vli_isZero(input, num_words)) {
|
||||
uECC_vli_clear(result, num_words);
|
||||
return;
|
||||
}
|
||||
|
||||
uECC_vli_set(a, input, num_words);
|
||||
uECC_vli_set(b, mod, num_words);
|
||||
uECC_vli_clear(u, num_words);
|
||||
u[0] = 1;
|
||||
uECC_vli_clear(v, num_words);
|
||||
while ((cmpResult = uECC_vli_cmp_unsafe(a, b, num_words)) != 0) {
|
||||
if (EVEN(a)) {
|
||||
uECC_vli_rshift1(a, num_words);
|
||||
vli_modInv_update(u, mod, num_words);
|
||||
} else if (EVEN(b)) {
|
||||
uECC_vli_rshift1(b, num_words);
|
||||
vli_modInv_update(v, mod, num_words);
|
||||
} else if (cmpResult > 0) {
|
||||
uECC_vli_sub(a, a, b, num_words);
|
||||
uECC_vli_rshift1(a, num_words);
|
||||
if (uECC_vli_cmp_unsafe(u, v, num_words) < 0) {
|
||||
uECC_vli_add(u, u, mod, num_words);
|
||||
}
|
||||
uECC_vli_sub(u, u, v, num_words);
|
||||
vli_modInv_update(u, mod, num_words);
|
||||
} else {
|
||||
uECC_vli_sub(b, b, a, num_words);
|
||||
uECC_vli_rshift1(b, num_words);
|
||||
if (uECC_vli_cmp_unsafe(v, u, num_words) < 0) {
|
||||
uECC_vli_add(v, v, mod, num_words);
|
||||
}
|
||||
uECC_vli_sub(v, v, u, num_words);
|
||||
vli_modInv_update(v, mod, num_words);
|
||||
}
|
||||
}
|
||||
uECC_vli_set(result, u, num_words);
|
||||
}
|
||||
|
||||
/* ------ Point operations ------ */
|
||||
|
||||
void double_jacobian_default(uECC_word_t * X1, uECC_word_t * Y1,
|
||||
uECC_word_t * Z1, uECC_Curve curve)
|
||||
{
|
||||
/* t1 = X, t2 = Y, t3 = Z */
|
||||
uECC_word_t t4[NUM_ECC_WORDS];
|
||||
uECC_word_t t5[NUM_ECC_WORDS];
|
||||
wordcount_t num_words = curve->num_words;
|
||||
|
||||
if (uECC_vli_isZero(Z1, num_words)) {
|
||||
return;
|
||||
}
|
||||
|
||||
uECC_vli_modSquare_fast(t4, Y1, curve); /* t4 = y1^2 */
|
||||
uECC_vli_modMult_fast(t5, X1, t4, curve); /* t5 = x1*y1^2 = A */
|
||||
uECC_vli_modSquare_fast(t4, t4, curve); /* t4 = y1^4 */
|
||||
uECC_vli_modMult_fast(Y1, Y1, Z1, curve); /* t2 = y1*z1 = z3 */
|
||||
uECC_vli_modSquare_fast(Z1, Z1, curve); /* t3 = z1^2 */
|
||||
|
||||
uECC_vli_modAdd(X1, X1, Z1, curve->p, num_words); /* t1 = x1 + z1^2 */
|
||||
uECC_vli_modAdd(Z1, Z1, Z1, curve->p, num_words); /* t3 = 2*z1^2 */
|
||||
uECC_vli_modSub(Z1, X1, Z1, curve->p, num_words); /* t3 = x1 - z1^2 */
|
||||
uECC_vli_modMult_fast(X1, X1, Z1, curve); /* t1 = x1^2 - z1^4 */
|
||||
|
||||
uECC_vli_modAdd(Z1, X1, X1, curve->p, num_words); /* t3 = 2*(x1^2 - z1^4) */
|
||||
uECC_vli_modAdd(X1, X1, Z1, curve->p, num_words); /* t1 = 3*(x1^2 - z1^4) */
|
||||
if (uECC_vli_testBit(X1, 0)) {
|
||||
uECC_word_t l_carry = uECC_vli_add(X1, X1, curve->p, num_words);
|
||||
uECC_vli_rshift1(X1, num_words);
|
||||
X1[num_words - 1] |= l_carry << (uECC_WORD_BITS - 1);
|
||||
} else {
|
||||
uECC_vli_rshift1(X1, num_words);
|
||||
}
|
||||
|
||||
/* t1 = 3/2*(x1^2 - z1^4) = B */
|
||||
uECC_vli_modSquare_fast(Z1, X1, curve); /* t3 = B^2 */
|
||||
uECC_vli_modSub(Z1, Z1, t5, curve->p, num_words); /* t3 = B^2 - A */
|
||||
uECC_vli_modSub(Z1, Z1, t5, curve->p, num_words); /* t3 = B^2 - 2A = x3 */
|
||||
uECC_vli_modSub(t5, t5, Z1, curve->p, num_words); /* t5 = A - x3 */
|
||||
uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = B * (A - x3) */
|
||||
/* t4 = B * (A - x3) - y1^4 = y3: */
|
||||
uECC_vli_modSub(t4, X1, t4, curve->p, num_words);
|
||||
|
||||
uECC_vli_set(X1, Z1, num_words);
|
||||
uECC_vli_set(Z1, Y1, num_words);
|
||||
uECC_vli_set(Y1, t4, num_words);
|
||||
}
|
||||
|
||||
void x_side_default(uECC_word_t *result,
|
||||
const uECC_word_t *x,
|
||||
uECC_Curve curve)
|
||||
{
|
||||
uECC_word_t _3[NUM_ECC_WORDS] = {3}; /* -a = 3 */
|
||||
wordcount_t num_words = curve->num_words;
|
||||
|
||||
uECC_vli_modSquare_fast(result, x, curve); /* r = x^2 */
|
||||
uECC_vli_modSub(result, result, _3, curve->p, num_words); /* r = x^2 - 3 */
|
||||
uECC_vli_modMult_fast(result, result, x, curve); /* r = x^3 - 3x */
|
||||
/* r = x^3 - 3x + b: */
|
||||
uECC_vli_modAdd(result, result, curve->b, curve->p, num_words);
|
||||
}
|
||||
|
||||
uECC_Curve uECC_secp256r1(void)
|
||||
{
|
||||
return &curve_secp256r1;
|
||||
}
|
||||
|
||||
void vli_mmod_fast_secp256r1(unsigned int *result, unsigned int*product)
|
||||
{
|
||||
unsigned int tmp[NUM_ECC_WORDS];
|
||||
int carry;
|
||||
|
||||
/* t */
|
||||
uECC_vli_set(result, product, NUM_ECC_WORDS);
|
||||
|
||||
/* s1 */
|
||||
tmp[0] = tmp[1] = tmp[2] = 0;
|
||||
tmp[3] = product[11];
|
||||
tmp[4] = product[12];
|
||||
tmp[5] = product[13];
|
||||
tmp[6] = product[14];
|
||||
tmp[7] = product[15];
|
||||
carry = uECC_vli_add(tmp, tmp, tmp, NUM_ECC_WORDS);
|
||||
carry += uECC_vli_add(result, result, tmp, NUM_ECC_WORDS);
|
||||
|
||||
/* s2 */
|
||||
tmp[3] = product[12];
|
||||
tmp[4] = product[13];
|
||||
tmp[5] = product[14];
|
||||
tmp[6] = product[15];
|
||||
tmp[7] = 0;
|
||||
carry += uECC_vli_add(tmp, tmp, tmp, NUM_ECC_WORDS);
|
||||
carry += uECC_vli_add(result, result, tmp, NUM_ECC_WORDS);
|
||||
|
||||
/* s3 */
|
||||
tmp[0] = product[8];
|
||||
tmp[1] = product[9];
|
||||
tmp[2] = product[10];
|
||||
tmp[3] = tmp[4] = tmp[5] = 0;
|
||||
tmp[6] = product[14];
|
||||
tmp[7] = product[15];
|
||||
carry += uECC_vli_add(result, result, tmp, NUM_ECC_WORDS);
|
||||
|
||||
/* s4 */
|
||||
tmp[0] = product[9];
|
||||
tmp[1] = product[10];
|
||||
tmp[2] = product[11];
|
||||
tmp[3] = product[13];
|
||||
tmp[4] = product[14];
|
||||
tmp[5] = product[15];
|
||||
tmp[6] = product[13];
|
||||
tmp[7] = product[8];
|
||||
carry += uECC_vli_add(result, result, tmp, NUM_ECC_WORDS);
|
||||
|
||||
/* d1 */
|
||||
tmp[0] = product[11];
|
||||
tmp[1] = product[12];
|
||||
tmp[2] = product[13];
|
||||
tmp[3] = tmp[4] = tmp[5] = 0;
|
||||
tmp[6] = product[8];
|
||||
tmp[7] = product[10];
|
||||
carry -= uECC_vli_sub(result, result, tmp, NUM_ECC_WORDS);
|
||||
|
||||
/* d2 */
|
||||
tmp[0] = product[12];
|
||||
tmp[1] = product[13];
|
||||
tmp[2] = product[14];
|
||||
tmp[3] = product[15];
|
||||
tmp[4] = tmp[5] = 0;
|
||||
tmp[6] = product[9];
|
||||
tmp[7] = product[11];
|
||||
carry -= uECC_vli_sub(result, result, tmp, NUM_ECC_WORDS);
|
||||
|
||||
/* d3 */
|
||||
tmp[0] = product[13];
|
||||
tmp[1] = product[14];
|
||||
tmp[2] = product[15];
|
||||
tmp[3] = product[8];
|
||||
tmp[4] = product[9];
|
||||
tmp[5] = product[10];
|
||||
tmp[6] = 0;
|
||||
tmp[7] = product[12];
|
||||
carry -= uECC_vli_sub(result, result, tmp, NUM_ECC_WORDS);
|
||||
|
||||
/* d4 */
|
||||
tmp[0] = product[14];
|
||||
tmp[1] = product[15];
|
||||
tmp[2] = 0;
|
||||
tmp[3] = product[9];
|
||||
tmp[4] = product[10];
|
||||
tmp[5] = product[11];
|
||||
tmp[6] = 0;
|
||||
tmp[7] = product[13];
|
||||
carry -= uECC_vli_sub(result, result, tmp, NUM_ECC_WORDS);
|
||||
|
||||
if (carry < 0) {
|
||||
do {
|
||||
carry += uECC_vli_add(result, result, curve_secp256r1.p, NUM_ECC_WORDS);
|
||||
}
|
||||
while (carry < 0);
|
||||
} else {
|
||||
while (carry ||
|
||||
uECC_vli_cmp_unsafe(curve_secp256r1.p, result, NUM_ECC_WORDS) != 1) {
|
||||
carry -= uECC_vli_sub(result, result, curve_secp256r1.p, NUM_ECC_WORDS);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uECC_word_t EccPoint_isZero(const uECC_word_t *point, uECC_Curve curve)
|
||||
{
|
||||
return uECC_vli_isZero(point, curve->num_words * 2);
|
||||
}
|
||||
|
||||
void apply_z(uECC_word_t * X1, uECC_word_t * Y1, const uECC_word_t * const Z,
|
||||
uECC_Curve curve)
|
||||
{
|
||||
uECC_word_t t1[NUM_ECC_WORDS];
|
||||
|
||||
uECC_vli_modSquare_fast(t1, Z, curve); /* z^2 */
|
||||
uECC_vli_modMult_fast(X1, X1, t1, curve); /* x1 * z^2 */
|
||||
uECC_vli_modMult_fast(t1, t1, Z, curve); /* z^3 */
|
||||
uECC_vli_modMult_fast(Y1, Y1, t1, curve); /* y1 * z^3 */
|
||||
}
|
||||
|
||||
/* P = (x1, y1) => 2P, (x2, y2) => P' */
|
||||
static void XYcZ_initial_double(uECC_word_t * X1, uECC_word_t * Y1,
|
||||
uECC_word_t * X2, uECC_word_t * Y2,
|
||||
const uECC_word_t * const initial_Z,
|
||||
uECC_Curve curve)
|
||||
{
|
||||
uECC_word_t z[NUM_ECC_WORDS];
|
||||
wordcount_t num_words = curve->num_words;
|
||||
if (initial_Z) {
|
||||
uECC_vli_set(z, initial_Z, num_words);
|
||||
} else {
|
||||
uECC_vli_clear(z, num_words);
|
||||
z[0] = 1;
|
||||
}
|
||||
|
||||
uECC_vli_set(X2, X1, num_words);
|
||||
uECC_vli_set(Y2, Y1, num_words);
|
||||
|
||||
apply_z(X1, Y1, z, curve);
|
||||
curve->double_jacobian(X1, Y1, z, curve);
|
||||
apply_z(X2, Y2, z, curve);
|
||||
}
|
||||
|
||||
void XYcZ_add(uECC_word_t * X1, uECC_word_t * Y1,
|
||||
uECC_word_t * X2, uECC_word_t * Y2,
|
||||
uECC_Curve curve)
|
||||
{
|
||||
/* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
|
||||
uECC_word_t t5[NUM_ECC_WORDS];
|
||||
wordcount_t num_words = curve->num_words;
|
||||
|
||||
uECC_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */
|
||||
uECC_vli_modSquare_fast(t5, t5, curve); /* t5 = (x2 - x1)^2 = A */
|
||||
uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = x1*A = B */
|
||||
uECC_vli_modMult_fast(X2, X2, t5, curve); /* t3 = x2*A = C */
|
||||
uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y2 - y1 */
|
||||
uECC_vli_modSquare_fast(t5, Y2, curve); /* t5 = (y2 - y1)^2 = D */
|
||||
|
||||
uECC_vli_modSub(t5, t5, X1, curve->p, num_words); /* t5 = D - B */
|
||||
uECC_vli_modSub(t5, t5, X2, curve->p, num_words); /* t5 = D - B - C = x3 */
|
||||
uECC_vli_modSub(X2, X2, X1, curve->p, num_words); /* t3 = C - B */
|
||||
uECC_vli_modMult_fast(Y1, Y1, X2, curve); /* t2 = y1*(C - B) */
|
||||
uECC_vli_modSub(X2, X1, t5, curve->p, num_words); /* t3 = B - x3 */
|
||||
uECC_vli_modMult_fast(Y2, Y2, X2, curve); /* t4 = (y2 - y1)*(B - x3) */
|
||||
uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y3 */
|
||||
|
||||
uECC_vli_set(X2, t5, num_words);
|
||||
}
|
||||
|
||||
/* Input P = (x1, y1, Z), Q = (x2, y2, Z)
|
||||
Output P + Q = (x3, y3, Z3), P - Q = (x3', y3', Z3)
|
||||
or P => P - Q, Q => P + Q
|
||||
*/
|
||||
static void XYcZ_addC(uECC_word_t * X1, uECC_word_t * Y1,
|
||||
uECC_word_t * X2, uECC_word_t * Y2,
|
||||
uECC_Curve curve)
|
||||
{
|
||||
/* t1 = X1, t2 = Y1, t3 = X2, t4 = Y2 */
|
||||
uECC_word_t t5[NUM_ECC_WORDS];
|
||||
uECC_word_t t6[NUM_ECC_WORDS];
|
||||
uECC_word_t t7[NUM_ECC_WORDS];
|
||||
wordcount_t num_words = curve->num_words;
|
||||
|
||||
uECC_vli_modSub(t5, X2, X1, curve->p, num_words); /* t5 = x2 - x1 */
|
||||
uECC_vli_modSquare_fast(t5, t5, curve); /* t5 = (x2 - x1)^2 = A */
|
||||
uECC_vli_modMult_fast(X1, X1, t5, curve); /* t1 = x1*A = B */
|
||||
uECC_vli_modMult_fast(X2, X2, t5, curve); /* t3 = x2*A = C */
|
||||
uECC_vli_modAdd(t5, Y2, Y1, curve->p, num_words); /* t5 = y2 + y1 */
|
||||
uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words); /* t4 = y2 - y1 */
|
||||
|
||||
uECC_vli_modSub(t6, X2, X1, curve->p, num_words); /* t6 = C - B */
|
||||
uECC_vli_modMult_fast(Y1, Y1, t6, curve); /* t2 = y1 * (C - B) = E */
|
||||
uECC_vli_modAdd(t6, X1, X2, curve->p, num_words); /* t6 = B + C */
|
||||
uECC_vli_modSquare_fast(X2, Y2, curve); /* t3 = (y2 - y1)^2 = D */
|
||||
uECC_vli_modSub(X2, X2, t6, curve->p, num_words); /* t3 = D - (B + C) = x3 */
|
||||
|
||||
uECC_vli_modSub(t7, X1, X2, curve->p, num_words); /* t7 = B - x3 */
|
||||
uECC_vli_modMult_fast(Y2, Y2, t7, curve); /* t4 = (y2 - y1)*(B - x3) */
|
||||
/* t4 = (y2 - y1)*(B - x3) - E = y3: */
|
||||
uECC_vli_modSub(Y2, Y2, Y1, curve->p, num_words);
|
||||
|
||||
uECC_vli_modSquare_fast(t7, t5, curve); /* t7 = (y2 + y1)^2 = F */
|
||||
uECC_vli_modSub(t7, t7, t6, curve->p, num_words); /* t7 = F - (B + C) = x3' */
|
||||
uECC_vli_modSub(t6, t7, X1, curve->p, num_words); /* t6 = x3' - B */
|
||||
uECC_vli_modMult_fast(t6, t6, t5, curve); /* t6 = (y2+y1)*(x3' - B) */
|
||||
/* t2 = (y2+y1)*(x3' - B) - E = y3': */
|
||||
uECC_vli_modSub(Y1, t6, Y1, curve->p, num_words);
|
||||
|
||||
uECC_vli_set(X1, t7, num_words);
|
||||
}
|
||||
|
||||
void EccPoint_mult(uECC_word_t * result, const uECC_word_t * point,
|
||||
const uECC_word_t * scalar,
|
||||
const uECC_word_t * initial_Z,
|
||||
bitcount_t num_bits, uECC_Curve curve)
|
||||
{
|
||||
/* R0 and R1 */
|
||||
uECC_word_t Rx[2][NUM_ECC_WORDS];
|
||||
uECC_word_t Ry[2][NUM_ECC_WORDS];
|
||||
uECC_word_t z[NUM_ECC_WORDS];
|
||||
bitcount_t i;
|
||||
uECC_word_t nb;
|
||||
wordcount_t num_words = curve->num_words;
|
||||
|
||||
uECC_vli_set(Rx[1], point, num_words);
|
||||
uECC_vli_set(Ry[1], point + num_words, num_words);
|
||||
|
||||
XYcZ_initial_double(Rx[1], Ry[1], Rx[0], Ry[0], initial_Z, curve);
|
||||
|
||||
for (i = num_bits - 2; i > 0; --i) {
|
||||
nb = !uECC_vli_testBit(scalar, i);
|
||||
XYcZ_addC(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], curve);
|
||||
XYcZ_add(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], curve);
|
||||
}
|
||||
|
||||
nb = !uECC_vli_testBit(scalar, 0);
|
||||
XYcZ_addC(Rx[1 - nb], Ry[1 - nb], Rx[nb], Ry[nb], curve);
|
||||
|
||||
/* Find final 1/Z value. */
|
||||
uECC_vli_modSub(z, Rx[1], Rx[0], curve->p, num_words); /* X1 - X0 */
|
||||
uECC_vli_modMult_fast(z, z, Ry[1 - nb], curve); /* Yb * (X1 - X0) */
|
||||
uECC_vli_modMult_fast(z, z, point, curve); /* xP * Yb * (X1 - X0) */
|
||||
uECC_vli_modInv(z, z, curve->p, num_words); /* 1 / (xP * Yb * (X1 - X0))*/
|
||||
/* yP / (xP * Yb * (X1 - X0)) */
|
||||
uECC_vli_modMult_fast(z, z, point + num_words, curve);
|
||||
/* Xb * yP / (xP * Yb * (X1 - X0)) */
|
||||
uECC_vli_modMult_fast(z, z, Rx[1 - nb], curve);
|
||||
/* End 1/Z calculation */
|
||||
|
||||
XYcZ_add(Rx[nb], Ry[nb], Rx[1 - nb], Ry[1 - nb], curve);
|
||||
apply_z(Rx[0], Ry[0], z, curve);
|
||||
|
||||
uECC_vli_set(result, Rx[0], num_words);
|
||||
uECC_vli_set(result + num_words, Ry[0], num_words);
|
||||
}
|
||||
|
||||
uECC_word_t regularize_k(const uECC_word_t * const k, uECC_word_t *k0,
|
||||
uECC_word_t *k1, uECC_Curve curve)
|
||||
{
|
||||
|
||||
wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
|
||||
|
||||
bitcount_t num_n_bits = curve->num_n_bits;
|
||||
|
||||
uECC_word_t carry = uECC_vli_add(k0, k, curve->n, num_n_words) ||
|
||||
(num_n_bits < ((bitcount_t)num_n_words * uECC_WORD_SIZE * 8) &&
|
||||
uECC_vli_testBit(k0, num_n_bits));
|
||||
|
||||
uECC_vli_add(k1, k0, curve->n, num_n_words);
|
||||
|
||||
return carry;
|
||||
}
|
||||
|
||||
uECC_word_t EccPoint_compute_public_key(uECC_word_t *result,
|
||||
uECC_word_t *private_key,
|
||||
uECC_Curve curve)
|
||||
{
|
||||
|
||||
uECC_word_t tmp1[NUM_ECC_WORDS];
|
||||
uECC_word_t tmp2[NUM_ECC_WORDS];
|
||||
uECC_word_t *p2[2] = {tmp1, tmp2};
|
||||
uECC_word_t carry;
|
||||
|
||||
/* Regularize the bitcount for the private key so that attackers cannot
|
||||
* use a side channel attack to learn the number of leading zeros. */
|
||||
carry = regularize_k(private_key, tmp1, tmp2, curve);
|
||||
|
||||
EccPoint_mult(result, curve->G, p2[!carry], 0, curve->num_n_bits + 1, curve);
|
||||
|
||||
if (EccPoint_isZero(result, curve)) {
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Converts an integer in uECC native format to big-endian bytes. */
|
||||
void uECC_vli_nativeToBytes(uint8_t *bytes, int num_bytes,
|
||||
const unsigned int *native)
|
||||
{
|
||||
wordcount_t i;
|
||||
for (i = 0; i < num_bytes; ++i) {
|
||||
unsigned b = num_bytes - 1 - i;
|
||||
bytes[i] = native[b / uECC_WORD_SIZE] >> (8 * (b % uECC_WORD_SIZE));
|
||||
}
|
||||
}
|
||||
|
||||
/* Converts big-endian bytes to an integer in uECC native format. */
|
||||
void uECC_vli_bytesToNative(unsigned int *native, const uint8_t *bytes,
|
||||
int num_bytes)
|
||||
{
|
||||
wordcount_t i;
|
||||
uECC_vli_clear(native, (num_bytes + (uECC_WORD_SIZE - 1)) / uECC_WORD_SIZE);
|
||||
for (i = 0; i < num_bytes; ++i) {
|
||||
unsigned b = num_bytes - 1 - i;
|
||||
native[b / uECC_WORD_SIZE] |=
|
||||
(uECC_word_t)bytes[i] << (8 * (b % uECC_WORD_SIZE));
|
||||
}
|
||||
}
|
||||
|
||||
int uECC_generate_random_int(uECC_word_t *random, const uECC_word_t *top,
|
||||
wordcount_t num_words)
|
||||
{
|
||||
uECC_word_t mask = (uECC_word_t)-1;
|
||||
uECC_word_t tries;
|
||||
bitcount_t num_bits = uECC_vli_numBits(top, num_words);
|
||||
|
||||
if (!g_rng_function) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) {
|
||||
if (!g_rng_function((uint8_t *)random, num_words * uECC_WORD_SIZE)) {
|
||||
return 0;
|
||||
}
|
||||
random[num_words - 1] &=
|
||||
mask >> ((bitcount_t)(num_words * uECC_WORD_SIZE * 8 - num_bits));
|
||||
if (!uECC_vli_isZero(random, num_words) &&
|
||||
uECC_vli_cmp(top, random, num_words) == 1) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int uECC_valid_point(const uECC_word_t *point, uECC_Curve curve)
|
||||
{
|
||||
uECC_word_t tmp1[NUM_ECC_WORDS];
|
||||
uECC_word_t tmp2[NUM_ECC_WORDS];
|
||||
wordcount_t num_words = curve->num_words;
|
||||
|
||||
/* The point at infinity is invalid. */
|
||||
if (EccPoint_isZero(point, curve)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* x and y must be smaller than p. */
|
||||
if (uECC_vli_cmp_unsafe(curve->p, point, num_words) != 1 ||
|
||||
uECC_vli_cmp_unsafe(curve->p, point + num_words, num_words) != 1) {
|
||||
return -2;
|
||||
}
|
||||
|
||||
uECC_vli_modSquare_fast(tmp1, point + num_words, curve);
|
||||
curve->x_side(tmp2, point, curve); /* tmp2 = x^3 + ax + b */
|
||||
|
||||
/* Make sure that y^2 == x^3 + ax + b */
|
||||
if (uECC_vli_equal(tmp1, tmp2, num_words) != 0)
|
||||
return -3;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uECC_valid_public_key(const uint8_t *public_key, uECC_Curve curve)
|
||||
{
|
||||
|
||||
uECC_word_t _public[NUM_ECC_WORDS * 2];
|
||||
|
||||
uECC_vli_bytesToNative(_public, public_key, curve->num_bytes);
|
||||
uECC_vli_bytesToNative(
|
||||
_public + curve->num_words,
|
||||
public_key + curve->num_bytes,
|
||||
curve->num_bytes);
|
||||
|
||||
if (uECC_vli_cmp_unsafe(_public, curve->G, NUM_ECC_WORDS * 2) == 0) {
|
||||
return -4;
|
||||
}
|
||||
|
||||
return uECC_valid_point(_public, curve);
|
||||
}
|
||||
|
||||
int uECC_compute_public_key(const uint8_t *private_key, uint8_t *public_key,
|
||||
uECC_Curve curve)
|
||||
{
|
||||
|
||||
uECC_word_t _private[NUM_ECC_WORDS];
|
||||
uECC_word_t _public[NUM_ECC_WORDS * 2];
|
||||
|
||||
uECC_vli_bytesToNative(
|
||||
_private,
|
||||
private_key,
|
||||
BITS_TO_BYTES(curve->num_n_bits));
|
||||
|
||||
/* Make sure the private key is in the range [1, n-1]. */
|
||||
if (uECC_vli_isZero(_private, BITS_TO_WORDS(curve->num_n_bits))) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (uECC_vli_cmp(curve->n, _private, BITS_TO_WORDS(curve->num_n_bits)) != 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Compute public key. */
|
||||
if (!EccPoint_compute_public_key(_public, _private, curve)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uECC_vli_nativeToBytes(public_key, curve->num_bytes, _public);
|
||||
uECC_vli_nativeToBytes(
|
||||
public_key +
|
||||
curve->num_bytes, curve->num_bytes, _public + curve->num_words);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
|
||||
200
lib/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ecc_dh.c
Normal file
200
lib/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ecc_dh.c
Normal file
@@ -0,0 +1,200 @@
|
||||
/* ec_dh.c - TinyCrypt implementation of EC-DH */
|
||||
|
||||
/*
|
||||
* Copyright (c) 2014, Kenneth MacKay
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
#include "../include/tinycrypt/constants.h"
|
||||
#include "../include/tinycrypt/ecc.h"
|
||||
#include "../include/tinycrypt/ecc_dh.h"
|
||||
#include <string.h>
|
||||
|
||||
#if default_RNG_defined
|
||||
static uECC_RNG_Function g_rng_function = &default_CSPRNG;
|
||||
#else
|
||||
static uECC_RNG_Function g_rng_function = 0;
|
||||
#endif
|
||||
|
||||
int uECC_make_key_with_d(uint8_t *public_key, uint8_t *private_key,
|
||||
unsigned int *d, uECC_Curve curve)
|
||||
{
|
||||
|
||||
uECC_word_t _private[NUM_ECC_WORDS];
|
||||
uECC_word_t _public[NUM_ECC_WORDS * 2];
|
||||
|
||||
/* This function is designed for test purposes-only (such as validating NIST
|
||||
* test vectors) as it uses a provided value for d instead of generating
|
||||
* it uniformly at random. */
|
||||
memcpy (_private, d, NUM_ECC_BYTES);
|
||||
|
||||
/* Computing public-key from private: */
|
||||
if (EccPoint_compute_public_key(_public, _private, curve)) {
|
||||
|
||||
/* Converting buffers to correct bit order: */
|
||||
uECC_vli_nativeToBytes(private_key,
|
||||
BITS_TO_BYTES(curve->num_n_bits),
|
||||
_private);
|
||||
uECC_vli_nativeToBytes(public_key,
|
||||
curve->num_bytes,
|
||||
_public);
|
||||
uECC_vli_nativeToBytes(public_key + curve->num_bytes,
|
||||
curve->num_bytes,
|
||||
_public + curve->num_words);
|
||||
|
||||
/* erasing temporary buffer used to store secret: */
|
||||
memset(_private, 0, NUM_ECC_BYTES);
|
||||
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uECC_make_key(uint8_t *public_key, uint8_t *private_key, uECC_Curve curve)
|
||||
{
|
||||
|
||||
uECC_word_t _random[NUM_ECC_WORDS * 2];
|
||||
uECC_word_t _private[NUM_ECC_WORDS];
|
||||
uECC_word_t _public[NUM_ECC_WORDS * 2];
|
||||
uECC_word_t tries;
|
||||
|
||||
for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) {
|
||||
/* Generating _private uniformly at random: */
|
||||
uECC_RNG_Function rng_function = uECC_get_rng();
|
||||
if (!rng_function ||
|
||||
!rng_function((uint8_t *)_random, 2 * NUM_ECC_WORDS*uECC_WORD_SIZE)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* computing modular reduction of _random (see FIPS 186.4 B.4.1): */
|
||||
uECC_vli_mmod(_private, _random, curve->n, BITS_TO_WORDS(curve->num_n_bits));
|
||||
|
||||
/* Computing public-key from private: */
|
||||
if (EccPoint_compute_public_key(_public, _private, curve)) {
|
||||
|
||||
/* Converting buffers to correct bit order: */
|
||||
uECC_vli_nativeToBytes(private_key,
|
||||
BITS_TO_BYTES(curve->num_n_bits),
|
||||
_private);
|
||||
uECC_vli_nativeToBytes(public_key,
|
||||
curve->num_bytes,
|
||||
_public);
|
||||
uECC_vli_nativeToBytes(public_key + curve->num_bytes,
|
||||
curve->num_bytes,
|
||||
_public + curve->num_words);
|
||||
|
||||
/* erasing temporary buffer that stored secret: */
|
||||
memset(_private, 0, NUM_ECC_BYTES);
|
||||
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int uECC_shared_secret(const uint8_t *public_key, const uint8_t *private_key,
|
||||
uint8_t *secret, uECC_Curve curve)
|
||||
{
|
||||
|
||||
uECC_word_t _public[NUM_ECC_WORDS * 2];
|
||||
uECC_word_t _private[NUM_ECC_WORDS];
|
||||
|
||||
uECC_word_t tmp[NUM_ECC_WORDS];
|
||||
uECC_word_t *p2[2] = {_private, tmp};
|
||||
uECC_word_t *initial_Z = 0;
|
||||
uECC_word_t carry;
|
||||
wordcount_t num_words = curve->num_words;
|
||||
wordcount_t num_bytes = curve->num_bytes;
|
||||
int r;
|
||||
|
||||
/* Converting buffers to correct bit order: */
|
||||
uECC_vli_bytesToNative(_private,
|
||||
private_key,
|
||||
BITS_TO_BYTES(curve->num_n_bits));
|
||||
uECC_vli_bytesToNative(_public,
|
||||
public_key,
|
||||
num_bytes);
|
||||
uECC_vli_bytesToNative(_public + num_words,
|
||||
public_key + num_bytes,
|
||||
num_bytes);
|
||||
|
||||
/* Regularize the bitcount for the private key so that attackers cannot use a
|
||||
* side channel attack to learn the number of leading zeros. */
|
||||
carry = regularize_k(_private, _private, tmp, curve);
|
||||
|
||||
/* If an RNG function was specified, try to get a random initial Z value to
|
||||
* improve protection against side-channel attacks. */
|
||||
if (g_rng_function) {
|
||||
if (!uECC_generate_random_int(p2[carry], curve->p, num_words)) {
|
||||
r = 0;
|
||||
goto clear_and_out;
|
||||
}
|
||||
initial_Z = p2[carry];
|
||||
}
|
||||
|
||||
EccPoint_mult(_public, _public, p2[!carry], initial_Z, curve->num_n_bits + 1,
|
||||
curve);
|
||||
|
||||
uECC_vli_nativeToBytes(secret, num_bytes, _public);
|
||||
r = !EccPoint_isZero(_public, curve);
|
||||
|
||||
clear_and_out:
|
||||
/* erasing temporary buffer used to store secret: */
|
||||
memset(p2, 0, sizeof(p2));
|
||||
__asm__ __volatile__("" :: "g"(p2) : "memory");
|
||||
memset(tmp, 0, sizeof(tmp));
|
||||
__asm__ __volatile__("" :: "g"(tmp) : "memory");
|
||||
memset(_private, 0, sizeof(_private));
|
||||
__asm__ __volatile__("" :: "g"(_private) : "memory");
|
||||
|
||||
return r;
|
||||
}
|
||||
295
lib/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ecc_dsa.c
Normal file
295
lib/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/ecc_dsa.c
Normal file
@@ -0,0 +1,295 @@
|
||||
/* ec_dsa.c - TinyCrypt implementation of EC-DSA */
|
||||
|
||||
/* Copyright (c) 2014, Kenneth MacKay
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "../include/tinycrypt/constants.h"
|
||||
#include "../include/tinycrypt/ecc.h"
|
||||
#include "../include/tinycrypt/ecc_dsa.h"
|
||||
|
||||
#if default_RNG_defined
|
||||
static uECC_RNG_Function g_rng_function = &default_CSPRNG;
|
||||
#else
|
||||
static uECC_RNG_Function g_rng_function = 0;
|
||||
#endif
|
||||
|
||||
static void bits2int(uECC_word_t *native, const uint8_t *bits,
|
||||
unsigned bits_size, uECC_Curve curve)
|
||||
{
|
||||
unsigned num_n_bytes = BITS_TO_BYTES(curve->num_n_bits);
|
||||
unsigned num_n_words = BITS_TO_WORDS(curve->num_n_bits);
|
||||
int shift;
|
||||
uECC_word_t carry;
|
||||
uECC_word_t *ptr;
|
||||
|
||||
if (bits_size > num_n_bytes) {
|
||||
bits_size = num_n_bytes;
|
||||
}
|
||||
|
||||
uECC_vli_clear(native, num_n_words);
|
||||
uECC_vli_bytesToNative(native, bits, bits_size);
|
||||
if (bits_size * 8 <= (unsigned)curve->num_n_bits) {
|
||||
return;
|
||||
}
|
||||
shift = bits_size * 8 - curve->num_n_bits;
|
||||
carry = 0;
|
||||
ptr = native + num_n_words;
|
||||
while (ptr-- > native) {
|
||||
uECC_word_t temp = *ptr;
|
||||
*ptr = (temp >> shift) | carry;
|
||||
carry = temp << (uECC_WORD_BITS - shift);
|
||||
}
|
||||
|
||||
/* Reduce mod curve_n */
|
||||
if (uECC_vli_cmp_unsafe(curve->n, native, num_n_words) != 1) {
|
||||
uECC_vli_sub(native, native, curve->n, num_n_words);
|
||||
}
|
||||
}
|
||||
|
||||
int uECC_sign_with_k(const uint8_t *private_key, const uint8_t *message_hash,
|
||||
unsigned hash_size, uECC_word_t *k, uint8_t *signature,
|
||||
uECC_Curve curve)
|
||||
{
|
||||
|
||||
uECC_word_t tmp[NUM_ECC_WORDS];
|
||||
uECC_word_t s[NUM_ECC_WORDS];
|
||||
uECC_word_t *k2[2] = {tmp, s};
|
||||
uECC_word_t p[NUM_ECC_WORDS * 2];
|
||||
uECC_word_t carry;
|
||||
wordcount_t num_words = curve->num_words;
|
||||
wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
|
||||
bitcount_t num_n_bits = curve->num_n_bits;
|
||||
|
||||
/* Make sure 0 < k < curve_n */
|
||||
if (uECC_vli_isZero(k, num_words) ||
|
||||
uECC_vli_cmp(curve->n, k, num_n_words) != 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
carry = regularize_k(k, tmp, s, curve);
|
||||
EccPoint_mult(p, curve->G, k2[!carry], 0, num_n_bits + 1, curve);
|
||||
if (uECC_vli_isZero(p, num_words)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* If an RNG function was specified, get a random number
|
||||
to prevent side channel analysis of k. */
|
||||
if (!g_rng_function) {
|
||||
uECC_vli_clear(tmp, num_n_words);
|
||||
tmp[0] = 1;
|
||||
}
|
||||
else if (!uECC_generate_random_int(tmp, curve->n, num_n_words)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Prevent side channel analysis of uECC_vli_modInv() to determine
|
||||
bits of k / the private key by premultiplying by a random number */
|
||||
uECC_vli_modMult(k, k, tmp, curve->n, num_n_words); /* k' = rand * k */
|
||||
uECC_vli_modInv(k, k, curve->n, num_n_words); /* k = 1 / k' */
|
||||
uECC_vli_modMult(k, k, tmp, curve->n, num_n_words); /* k = 1 / k */
|
||||
|
||||
uECC_vli_nativeToBytes(signature, curve->num_bytes, p); /* store r */
|
||||
|
||||
/* tmp = d: */
|
||||
uECC_vli_bytesToNative(tmp, private_key, BITS_TO_BYTES(curve->num_n_bits));
|
||||
|
||||
s[num_n_words - 1] = 0;
|
||||
uECC_vli_set(s, p, num_words);
|
||||
uECC_vli_modMult(s, tmp, s, curve->n, num_n_words); /* s = r*d */
|
||||
|
||||
bits2int(tmp, message_hash, hash_size, curve);
|
||||
uECC_vli_modAdd(s, tmp, s, curve->n, num_n_words); /* s = e + r*d */
|
||||
uECC_vli_modMult(s, s, k, curve->n, num_n_words); /* s = (e + r*d) / k */
|
||||
if (uECC_vli_numBits(s, num_n_words) > (bitcount_t)curve->num_bytes * 8) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
uECC_vli_nativeToBytes(signature + curve->num_bytes, curve->num_bytes, s);
|
||||
return 1;
|
||||
}
|
||||
|
||||
int uECC_sign(const uint8_t *private_key, const uint8_t *message_hash,
|
||||
unsigned hash_size, uint8_t *signature, uECC_Curve curve)
|
||||
{
|
||||
uECC_word_t _random[2*NUM_ECC_WORDS];
|
||||
uECC_word_t k[NUM_ECC_WORDS];
|
||||
uECC_word_t tries;
|
||||
|
||||
for (tries = 0; tries < uECC_RNG_MAX_TRIES; ++tries) {
|
||||
/* Generating _random uniformly at random: */
|
||||
uECC_RNG_Function rng_function = uECC_get_rng();
|
||||
if (!rng_function ||
|
||||
!rng_function((uint8_t *)_random, 2*NUM_ECC_WORDS*uECC_WORD_SIZE)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// computing k as modular reduction of _random (see FIPS 186.4 B.5.1):
|
||||
uECC_vli_mmod(k, _random, curve->n, BITS_TO_WORDS(curve->num_n_bits));
|
||||
|
||||
if (uECC_sign_with_k(private_key, message_hash, hash_size, k, signature,
|
||||
curve)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bitcount_t smax(bitcount_t a, bitcount_t b)
|
||||
{
|
||||
return (a > b ? a : b);
|
||||
}
|
||||
|
||||
int uECC_verify(const uint8_t *public_key, const uint8_t *message_hash,
|
||||
unsigned hash_size, const uint8_t *signature,
|
||||
uECC_Curve curve)
|
||||
{
|
||||
|
||||
uECC_word_t u1[NUM_ECC_WORDS], u2[NUM_ECC_WORDS];
|
||||
uECC_word_t z[NUM_ECC_WORDS];
|
||||
uECC_word_t sum[NUM_ECC_WORDS * 2];
|
||||
uECC_word_t rx[NUM_ECC_WORDS];
|
||||
uECC_word_t ry[NUM_ECC_WORDS];
|
||||
uECC_word_t tx[NUM_ECC_WORDS];
|
||||
uECC_word_t ty[NUM_ECC_WORDS];
|
||||
uECC_word_t tz[NUM_ECC_WORDS];
|
||||
const uECC_word_t *points[4];
|
||||
const uECC_word_t *point;
|
||||
bitcount_t num_bits;
|
||||
bitcount_t i;
|
||||
|
||||
uECC_word_t _public[NUM_ECC_WORDS * 2];
|
||||
uECC_word_t r[NUM_ECC_WORDS], s[NUM_ECC_WORDS];
|
||||
wordcount_t num_words = curve->num_words;
|
||||
wordcount_t num_n_words = BITS_TO_WORDS(curve->num_n_bits);
|
||||
|
||||
rx[num_n_words - 1] = 0;
|
||||
r[num_n_words - 1] = 0;
|
||||
s[num_n_words - 1] = 0;
|
||||
|
||||
uECC_vli_bytesToNative(_public, public_key, curve->num_bytes);
|
||||
uECC_vli_bytesToNative(_public + num_words, public_key + curve->num_bytes,
|
||||
curve->num_bytes);
|
||||
uECC_vli_bytesToNative(r, signature, curve->num_bytes);
|
||||
uECC_vli_bytesToNative(s, signature + curve->num_bytes, curve->num_bytes);
|
||||
|
||||
/* r, s must not be 0. */
|
||||
if (uECC_vli_isZero(r, num_words) || uECC_vli_isZero(s, num_words)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* r, s must be < n. */
|
||||
if (uECC_vli_cmp_unsafe(curve->n, r, num_n_words) != 1 ||
|
||||
uECC_vli_cmp_unsafe(curve->n, s, num_n_words) != 1) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Calculate u1 and u2. */
|
||||
uECC_vli_modInv(z, s, curve->n, num_n_words); /* z = 1/s */
|
||||
u1[num_n_words - 1] = 0;
|
||||
bits2int(u1, message_hash, hash_size, curve);
|
||||
uECC_vli_modMult(u1, u1, z, curve->n, num_n_words); /* u1 = e/s */
|
||||
uECC_vli_modMult(u2, r, z, curve->n, num_n_words); /* u2 = r/s */
|
||||
|
||||
/* Calculate sum = G + Q. */
|
||||
uECC_vli_set(sum, _public, num_words);
|
||||
uECC_vli_set(sum + num_words, _public + num_words, num_words);
|
||||
uECC_vli_set(tx, curve->G, num_words);
|
||||
uECC_vli_set(ty, curve->G + num_words, num_words);
|
||||
uECC_vli_modSub(z, sum, tx, curve->p, num_words); /* z = x2 - x1 */
|
||||
XYcZ_add(tx, ty, sum, sum + num_words, curve);
|
||||
uECC_vli_modInv(z, z, curve->p, num_words); /* z = 1/z */
|
||||
apply_z(sum, sum + num_words, z, curve);
|
||||
|
||||
/* Use Shamir's trick to calculate u1*G + u2*Q */
|
||||
points[0] = 0;
|
||||
points[1] = curve->G;
|
||||
points[2] = _public;
|
||||
points[3] = sum;
|
||||
num_bits = smax(uECC_vli_numBits(u1, num_n_words),
|
||||
uECC_vli_numBits(u2, num_n_words));
|
||||
|
||||
point = points[(!!uECC_vli_testBit(u1, num_bits - 1)) |
|
||||
((!!uECC_vli_testBit(u2, num_bits - 1)) << 1)];
|
||||
uECC_vli_set(rx, point, num_words);
|
||||
uECC_vli_set(ry, point + num_words, num_words);
|
||||
uECC_vli_clear(z, num_words);
|
||||
z[0] = 1;
|
||||
|
||||
for (i = num_bits - 2; i >= 0; --i) {
|
||||
uECC_word_t index;
|
||||
curve->double_jacobian(rx, ry, z, curve);
|
||||
|
||||
index = (!!uECC_vli_testBit(u1, i)) | ((!!uECC_vli_testBit(u2, i)) << 1);
|
||||
point = points[index];
|
||||
if (point) {
|
||||
uECC_vli_set(tx, point, num_words);
|
||||
uECC_vli_set(ty, point + num_words, num_words);
|
||||
apply_z(tx, ty, z, curve);
|
||||
uECC_vli_modSub(tz, rx, tx, curve->p, num_words); /* Z = x2 - x1 */
|
||||
XYcZ_add(tx, ty, rx, ry, curve);
|
||||
uECC_vli_modMult_fast(z, z, tz, curve);
|
||||
}
|
||||
}
|
||||
|
||||
uECC_vli_modInv(z, z, curve->p, num_words); /* Z = 1/Z */
|
||||
apply_z(rx, ry, z, curve);
|
||||
|
||||
/* v = x1 (mod n) */
|
||||
if (uECC_vli_cmp_unsafe(curve->n, rx, num_n_words) != 1) {
|
||||
uECC_vli_sub(rx, rx, curve->n, num_n_words);
|
||||
}
|
||||
|
||||
/* Accept only if v == r. */
|
||||
return (int)(uECC_vli_equal(rx, r, num_words) == 0);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,105 @@
|
||||
/* uECC_platform_specific.c - Implementation of platform specific functions*/
|
||||
|
||||
/* Copyright (c) 2014, Kenneth MacKay
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
* * Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.*/
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* uECC_platform_specific.c -- Implementation of platform specific functions
|
||||
*/
|
||||
|
||||
|
||||
#if defined(unix) || defined(__linux__) || defined(__unix__) || \
|
||||
defined(__unix) | (defined(__APPLE__) && defined(__MACH__)) || \
|
||||
defined(uECC_POSIX)
|
||||
|
||||
/* Some POSIX-like system with /dev/urandom or /dev/random. */
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef O_CLOEXEC
|
||||
#define O_CLOEXEC 0
|
||||
#endif
|
||||
|
||||
int default_CSPRNG(uint8_t *dest, unsigned int size) {
|
||||
|
||||
/* input sanity check: */
|
||||
if (dest == (uint8_t *) 0 || (size <= 0))
|
||||
return 0;
|
||||
|
||||
int fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC);
|
||||
if (fd == -1) {
|
||||
fd = open("/dev/random", O_RDONLY | O_CLOEXEC);
|
||||
if (fd == -1) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
char *ptr = (char *)dest;
|
||||
size_t left = (size_t) size;
|
||||
while (left > 0) {
|
||||
ssize_t bytes_read = read(fd, ptr, left);
|
||||
if (bytes_read <= 0) { // read failed
|
||||
close(fd);
|
||||
return 0;
|
||||
}
|
||||
left -= bytes_read;
|
||||
ptr += bytes_read;
|
||||
}
|
||||
|
||||
close(fd);
|
||||
return 1;
|
||||
}
|
||||
|
||||
#endif /* platform */
|
||||
|
||||
148
lib/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/hmac.c
Normal file
148
lib/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/hmac.c
Normal file
@@ -0,0 +1,148 @@
|
||||
/* hmac.c - TinyCrypt implementation of the HMAC algorithm */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "../include/tinycrypt/hmac.h"
|
||||
#include "../include/tinycrypt/constants.h"
|
||||
#include "../include/tinycrypt/utils.h"
|
||||
|
||||
static void rekey(uint8_t *key, const uint8_t *new_key, unsigned int key_size)
|
||||
{
|
||||
const uint8_t inner_pad = (uint8_t) 0x36;
|
||||
const uint8_t outer_pad = (uint8_t) 0x5c;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < key_size; ++i) {
|
||||
key[i] = inner_pad ^ new_key[i];
|
||||
key[i + TC_SHA256_BLOCK_SIZE] = outer_pad ^ new_key[i];
|
||||
}
|
||||
for (; i < TC_SHA256_BLOCK_SIZE; ++i) {
|
||||
key[i] = inner_pad; key[i + TC_SHA256_BLOCK_SIZE] = outer_pad;
|
||||
}
|
||||
}
|
||||
|
||||
int tc_hmac_set_key(TCHmacState_t ctx, const uint8_t *key,
|
||||
unsigned int key_size)
|
||||
{
|
||||
|
||||
/* input sanity check: */
|
||||
if (ctx == (TCHmacState_t) 0 ||
|
||||
key == (const uint8_t *) 0 ||
|
||||
key_size == 0) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
|
||||
const uint8_t dummy_key[key_size];
|
||||
struct tc_hmac_state_struct dummy_state;
|
||||
|
||||
if (key_size <= TC_SHA256_BLOCK_SIZE) {
|
||||
/*
|
||||
* The next three lines consist of dummy calls just to avoid
|
||||
* certain timing attacks. Without these dummy calls,
|
||||
* adversaries would be able to learn whether the key_size is
|
||||
* greater than TC_SHA256_BLOCK_SIZE by measuring the time
|
||||
* consumed in this process.
|
||||
*/
|
||||
(void)tc_sha256_init(&dummy_state.hash_state);
|
||||
(void)tc_sha256_update(&dummy_state.hash_state,
|
||||
dummy_key,
|
||||
key_size);
|
||||
(void)tc_sha256_final(&dummy_state.key[TC_SHA256_DIGEST_SIZE],
|
||||
&dummy_state.hash_state);
|
||||
|
||||
/* Actual code for when key_size <= TC_SHA256_BLOCK_SIZE: */
|
||||
rekey(ctx->key, key, key_size);
|
||||
} else {
|
||||
(void)tc_sha256_init(&ctx->hash_state);
|
||||
(void)tc_sha256_update(&ctx->hash_state, key, key_size);
|
||||
(void)tc_sha256_final(&ctx->key[TC_SHA256_DIGEST_SIZE],
|
||||
&ctx->hash_state);
|
||||
rekey(ctx->key,
|
||||
&ctx->key[TC_SHA256_DIGEST_SIZE],
|
||||
TC_SHA256_DIGEST_SIZE);
|
||||
}
|
||||
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
|
||||
int tc_hmac_init(TCHmacState_t ctx)
|
||||
{
|
||||
|
||||
/* input sanity check: */
|
||||
if (ctx == (TCHmacState_t) 0) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
|
||||
(void) tc_sha256_init(&ctx->hash_state);
|
||||
(void) tc_sha256_update(&ctx->hash_state, ctx->key, TC_SHA256_BLOCK_SIZE);
|
||||
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
|
||||
int tc_hmac_update(TCHmacState_t ctx,
|
||||
const void *data,
|
||||
unsigned int data_length)
|
||||
{
|
||||
|
||||
/* input sanity check: */
|
||||
if (ctx == (TCHmacState_t) 0) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
|
||||
(void)tc_sha256_update(&ctx->hash_state, data, data_length);
|
||||
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
|
||||
int tc_hmac_final(uint8_t *tag, unsigned int taglen, TCHmacState_t ctx)
|
||||
{
|
||||
|
||||
/* input sanity check: */
|
||||
if (tag == (uint8_t *) 0 ||
|
||||
taglen != TC_SHA256_DIGEST_SIZE ||
|
||||
ctx == (TCHmacState_t) 0) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
|
||||
(void) tc_sha256_final(tag, &ctx->hash_state);
|
||||
|
||||
(void)tc_sha256_init(&ctx->hash_state);
|
||||
(void)tc_sha256_update(&ctx->hash_state,
|
||||
&ctx->key[TC_SHA256_BLOCK_SIZE],
|
||||
TC_SHA256_BLOCK_SIZE);
|
||||
(void)tc_sha256_update(&ctx->hash_state, tag, TC_SHA256_DIGEST_SIZE);
|
||||
(void)tc_sha256_final(tag, &ctx->hash_state);
|
||||
|
||||
/* destroy the current state */
|
||||
_set(ctx, 0, sizeof(*ctx));
|
||||
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
212
lib/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/hmac_prng.c
Normal file
212
lib/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/hmac_prng.c
Normal file
@@ -0,0 +1,212 @@
|
||||
/* hmac_prng.c - TinyCrypt implementation of HMAC-PRNG */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "../include/tinycrypt/hmac_prng.h"
|
||||
#include "../include/tinycrypt/hmac.h"
|
||||
#include "../include/tinycrypt/constants.h"
|
||||
#include "../include/tinycrypt/utils.h"
|
||||
|
||||
/*
|
||||
* min bytes in the seed string.
|
||||
* MIN_SLEN*8 must be at least the expected security level.
|
||||
*/
|
||||
static const unsigned int MIN_SLEN = 32;
|
||||
|
||||
/*
|
||||
* max bytes in the seed string;
|
||||
* SP800-90A specifies a maximum of 2^35 bits (i.e., 2^32 bytes).
|
||||
*/
|
||||
static const unsigned int MAX_SLEN = UINT32_MAX;
|
||||
|
||||
/*
|
||||
* max bytes in the personalization string;
|
||||
* SP800-90A specifies a maximum of 2^35 bits (i.e., 2^32 bytes).
|
||||
*/
|
||||
static const unsigned int MAX_PLEN = UINT32_MAX;
|
||||
|
||||
/*
|
||||
* max bytes in the additional_info string;
|
||||
* SP800-90A specifies a maximum of 2^35 bits (i.e., 2^32 bytes).
|
||||
*/
|
||||
static const unsigned int MAX_ALEN = UINT32_MAX;
|
||||
|
||||
/*
|
||||
* max number of generates between re-seeds;
|
||||
* TinyCrypt accepts up to (2^32 - 1) which is the maximal value of
|
||||
* a 32-bit unsigned int variable, while SP800-90A specifies a maximum of 2^48.
|
||||
*/
|
||||
static const unsigned int MAX_GENS = UINT32_MAX;
|
||||
|
||||
/*
|
||||
* maximum bytes per generate call;
|
||||
* SP800-90A specifies a maximum up to 2^19.
|
||||
*/
|
||||
static const unsigned int MAX_OUT = (1 << 19);
|
||||
|
||||
/*
|
||||
* Assumes: prng != NULL, e != NULL, len >= 0.
|
||||
*/
|
||||
static void update(TCHmacPrng_t prng, const uint8_t *e, unsigned int len)
|
||||
{
|
||||
const uint8_t separator0 = 0x00;
|
||||
const uint8_t separator1 = 0x01;
|
||||
|
||||
/* use current state, e and separator 0 to compute a new prng key: */
|
||||
(void)tc_hmac_init(&prng->h);
|
||||
(void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v));
|
||||
(void)tc_hmac_update(&prng->h, &separator0, sizeof(separator0));
|
||||
(void)tc_hmac_update(&prng->h, e, len);
|
||||
(void)tc_hmac_final(prng->key, sizeof(prng->key), &prng->h);
|
||||
/* configure the new prng key into the prng's instance of hmac */
|
||||
(void)tc_hmac_set_key(&prng->h, prng->key, sizeof(prng->key));
|
||||
|
||||
/* use the new key to compute a new state variable v */
|
||||
(void)tc_hmac_init(&prng->h);
|
||||
(void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v));
|
||||
(void)tc_hmac_final(prng->v, sizeof(prng->v), &prng->h);
|
||||
|
||||
/* use current state, e and separator 1 to compute a new prng key: */
|
||||
(void)tc_hmac_init(&prng->h);
|
||||
(void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v));
|
||||
(void)tc_hmac_update(&prng->h, &separator1, sizeof(separator1));
|
||||
(void)tc_hmac_update(&prng->h, e, len);
|
||||
(void)tc_hmac_final(prng->key, sizeof(prng->key), &prng->h);
|
||||
/* configure the new prng key into the prng's instance of hmac */
|
||||
(void)tc_hmac_set_key(&prng->h, prng->key, sizeof(prng->key));
|
||||
|
||||
/* use the new key to compute a new state variable v */
|
||||
(void)tc_hmac_init(&prng->h);
|
||||
(void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v));
|
||||
(void)tc_hmac_final(prng->v, sizeof(prng->v), &prng->h);
|
||||
}
|
||||
|
||||
int tc_hmac_prng_init(TCHmacPrng_t prng,
|
||||
const uint8_t *personalization,
|
||||
unsigned int plen)
|
||||
{
|
||||
|
||||
/* input sanity check: */
|
||||
if (prng == (TCHmacPrng_t) 0 ||
|
||||
personalization == (uint8_t *) 0 ||
|
||||
plen > MAX_PLEN) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
|
||||
/* put the generator into a known state: */
|
||||
_set(prng->key, 0x00, sizeof(prng->key));
|
||||
_set(prng->v, 0x01, sizeof(prng->v));
|
||||
tc_hmac_set_key(&prng->h, prng->key, sizeof(prng->key));
|
||||
/* update assumes SOME key has been configured into HMAC */
|
||||
|
||||
update(prng, personalization, plen);
|
||||
|
||||
/* force a reseed before allowing tc_hmac_prng_generate to succeed: */
|
||||
prng->countdown = 0;
|
||||
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
|
||||
int tc_hmac_prng_reseed(TCHmacPrng_t prng,
|
||||
const uint8_t *seed,
|
||||
unsigned int seedlen,
|
||||
const uint8_t *additional_input,
|
||||
unsigned int additionallen)
|
||||
{
|
||||
|
||||
/* input sanity check: */
|
||||
if (prng == (TCHmacPrng_t) 0 ||
|
||||
seed == (const uint8_t *) 0 ||
|
||||
seedlen < MIN_SLEN ||
|
||||
seedlen > MAX_SLEN) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
|
||||
if (additional_input != (const uint8_t *) 0) {
|
||||
/*
|
||||
* Abort if additional_input is provided but has inappropriate
|
||||
* length
|
||||
*/
|
||||
if (additionallen == 0 ||
|
||||
additionallen > MAX_ALEN) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
} else {
|
||||
/* call update for the seed and additional_input */
|
||||
update(prng, seed, seedlen);
|
||||
update(prng, additional_input, additionallen);
|
||||
}
|
||||
} else {
|
||||
/* call update only for the seed */
|
||||
update(prng, seed, seedlen);
|
||||
}
|
||||
|
||||
/* ... and enable hmac_prng_generate */
|
||||
prng->countdown = MAX_GENS;
|
||||
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
|
||||
int tc_hmac_prng_generate(uint8_t *out, unsigned int outlen, TCHmacPrng_t prng)
|
||||
{
|
||||
unsigned int bufferlen;
|
||||
|
||||
/* input sanity check: */
|
||||
if (out == (uint8_t *) 0 ||
|
||||
prng == (TCHmacPrng_t) 0 ||
|
||||
outlen == 0 ||
|
||||
outlen > MAX_OUT) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
} else if (prng->countdown == 0) {
|
||||
return TC_HMAC_PRNG_RESEED_REQ;
|
||||
}
|
||||
|
||||
prng->countdown--;
|
||||
|
||||
while (outlen != 0) {
|
||||
/* operate HMAC in OFB mode to create "random" outputs */
|
||||
(void)tc_hmac_init(&prng->h);
|
||||
(void)tc_hmac_update(&prng->h, prng->v, sizeof(prng->v));
|
||||
(void)tc_hmac_final(prng->v, sizeof(prng->v), &prng->h);
|
||||
|
||||
bufferlen = (TC_SHA256_DIGEST_SIZE > outlen) ?
|
||||
outlen : TC_SHA256_DIGEST_SIZE;
|
||||
(void)_copy(out, bufferlen, prng->v, bufferlen);
|
||||
|
||||
out += bufferlen;
|
||||
outlen = (outlen > TC_SHA256_DIGEST_SIZE) ?
|
||||
(outlen - TC_SHA256_DIGEST_SIZE) : 0;
|
||||
}
|
||||
|
||||
/* block future PRNG compromises from revealing past state */
|
||||
update(prng, prng->v, TC_SHA256_DIGEST_SIZE);
|
||||
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
217
lib/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/sha256.c
Normal file
217
lib/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/sha256.c
Normal file
@@ -0,0 +1,217 @@
|
||||
/* sha256.c - TinyCrypt SHA-256 crypto hash algorithm implementation */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "../include/tinycrypt/sha256.h"
|
||||
#include "../include/tinycrypt/constants.h"
|
||||
#include "../include/tinycrypt/utils.h"
|
||||
|
||||
static void compress(unsigned int *iv, const uint8_t *data);
|
||||
|
||||
int tc_sha256_init(TCSha256State_t s)
|
||||
{
|
||||
/* input sanity check: */
|
||||
if (s == (TCSha256State_t) 0) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
|
||||
/*
|
||||
* Setting the initial state values.
|
||||
* These values correspond to the first 32 bits of the fractional parts
|
||||
* of the square roots of the first 8 primes: 2, 3, 5, 7, 11, 13, 17
|
||||
* and 19.
|
||||
*/
|
||||
_set((uint8_t *) s, 0x00, sizeof(*s));
|
||||
s->iv[0] = 0x6a09e667;
|
||||
s->iv[1] = 0xbb67ae85;
|
||||
s->iv[2] = 0x3c6ef372;
|
||||
s->iv[3] = 0xa54ff53a;
|
||||
s->iv[4] = 0x510e527f;
|
||||
s->iv[5] = 0x9b05688c;
|
||||
s->iv[6] = 0x1f83d9ab;
|
||||
s->iv[7] = 0x5be0cd19;
|
||||
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
|
||||
int tc_sha256_update(TCSha256State_t s, const uint8_t *data, size_t datalen)
|
||||
{
|
||||
/* input sanity check: */
|
||||
if (s == (TCSha256State_t) 0 ||
|
||||
data == (void *) 0) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
} else if (datalen == 0) {
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
|
||||
while (datalen-- > 0) {
|
||||
s->leftover[s->leftover_offset++] = *(data++);
|
||||
if (s->leftover_offset >= TC_SHA256_BLOCK_SIZE) {
|
||||
compress(s->iv, s->leftover);
|
||||
s->leftover_offset = 0;
|
||||
s->bits_hashed += (TC_SHA256_BLOCK_SIZE << 3);
|
||||
}
|
||||
}
|
||||
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
|
||||
int tc_sha256_final(uint8_t *digest, TCSha256State_t s)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
/* input sanity check: */
|
||||
if (digest == (uint8_t *) 0 ||
|
||||
s == (TCSha256State_t) 0) {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
|
||||
s->bits_hashed += (s->leftover_offset << 3);
|
||||
|
||||
s->leftover[s->leftover_offset++] = 0x80; /* always room for one byte */
|
||||
if (s->leftover_offset > (sizeof(s->leftover) - 8)) {
|
||||
/* there is not room for all the padding in this block */
|
||||
_set(s->leftover + s->leftover_offset, 0x00,
|
||||
sizeof(s->leftover) - s->leftover_offset);
|
||||
compress(s->iv, s->leftover);
|
||||
s->leftover_offset = 0;
|
||||
}
|
||||
|
||||
/* add the padding and the length in big-Endian format */
|
||||
_set(s->leftover + s->leftover_offset, 0x00,
|
||||
sizeof(s->leftover) - 8 - s->leftover_offset);
|
||||
s->leftover[sizeof(s->leftover) - 1] = (uint8_t)(s->bits_hashed);
|
||||
s->leftover[sizeof(s->leftover) - 2] = (uint8_t)(s->bits_hashed >> 8);
|
||||
s->leftover[sizeof(s->leftover) - 3] = (uint8_t)(s->bits_hashed >> 16);
|
||||
s->leftover[sizeof(s->leftover) - 4] = (uint8_t)(s->bits_hashed >> 24);
|
||||
s->leftover[sizeof(s->leftover) - 5] = (uint8_t)(s->bits_hashed >> 32);
|
||||
s->leftover[sizeof(s->leftover) - 6] = (uint8_t)(s->bits_hashed >> 40);
|
||||
s->leftover[sizeof(s->leftover) - 7] = (uint8_t)(s->bits_hashed >> 48);
|
||||
s->leftover[sizeof(s->leftover) - 8] = (uint8_t)(s->bits_hashed >> 56);
|
||||
|
||||
/* hash the padding and length */
|
||||
compress(s->iv, s->leftover);
|
||||
|
||||
/* copy the iv out to digest */
|
||||
for (i = 0; i < TC_SHA256_STATE_BLOCKS; ++i) {
|
||||
unsigned int t = *((unsigned int *) &s->iv[i]);
|
||||
*digest++ = (uint8_t)(t >> 24);
|
||||
*digest++ = (uint8_t)(t >> 16);
|
||||
*digest++ = (uint8_t)(t >> 8);
|
||||
*digest++ = (uint8_t)(t);
|
||||
}
|
||||
|
||||
/* destroy the current state */
|
||||
_set(s, 0, sizeof(*s));
|
||||
|
||||
return TC_CRYPTO_SUCCESS;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initializing SHA-256 Hash constant words K.
|
||||
* These values correspond to the first 32 bits of the fractional parts of the
|
||||
* cube roots of the first 64 primes between 2 and 311.
|
||||
*/
|
||||
static const unsigned int k256[64] = {
|
||||
0x428a2f98, 0x71374491, 0xb5c0fbcf, 0xe9b5dba5, 0x3956c25b, 0x59f111f1,
|
||||
0x923f82a4, 0xab1c5ed5, 0xd807aa98, 0x12835b01, 0x243185be, 0x550c7dc3,
|
||||
0x72be5d74, 0x80deb1fe, 0x9bdc06a7, 0xc19bf174, 0xe49b69c1, 0xefbe4786,
|
||||
0x0fc19dc6, 0x240ca1cc, 0x2de92c6f, 0x4a7484aa, 0x5cb0a9dc, 0x76f988da,
|
||||
0x983e5152, 0xa831c66d, 0xb00327c8, 0xbf597fc7, 0xc6e00bf3, 0xd5a79147,
|
||||
0x06ca6351, 0x14292967, 0x27b70a85, 0x2e1b2138, 0x4d2c6dfc, 0x53380d13,
|
||||
0x650a7354, 0x766a0abb, 0x81c2c92e, 0x92722c85, 0xa2bfe8a1, 0xa81a664b,
|
||||
0xc24b8b70, 0xc76c51a3, 0xd192e819, 0xd6990624, 0xf40e3585, 0x106aa070,
|
||||
0x19a4c116, 0x1e376c08, 0x2748774c, 0x34b0bcb5, 0x391c0cb3, 0x4ed8aa4a,
|
||||
0x5b9cca4f, 0x682e6ff3, 0x748f82ee, 0x78a5636f, 0x84c87814, 0x8cc70208,
|
||||
0x90befffa, 0xa4506ceb, 0xbef9a3f7, 0xc67178f2
|
||||
};
|
||||
|
||||
static inline unsigned int ROTR(unsigned int a, unsigned int n)
|
||||
{
|
||||
return (((a) >> n) | ((a) << (32 - n)));
|
||||
}
|
||||
|
||||
#define Sigma0(a)(ROTR((a), 2) ^ ROTR((a), 13) ^ ROTR((a), 22))
|
||||
#define Sigma1(a)(ROTR((a), 6) ^ ROTR((a), 11) ^ ROTR((a), 25))
|
||||
#define sigma0(a)(ROTR((a), 7) ^ ROTR((a), 18) ^ ((a) >> 3))
|
||||
#define sigma1(a)(ROTR((a), 17) ^ ROTR((a), 19) ^ ((a) >> 10))
|
||||
|
||||
#define Ch(a, b, c)(((a) & (b)) ^ ((~(a)) & (c)))
|
||||
#define Maj(a, b, c)(((a) & (b)) ^ ((a) & (c)) ^ ((b) & (c)))
|
||||
|
||||
static inline unsigned int BigEndian(const uint8_t **c)
|
||||
{
|
||||
unsigned int n = 0;
|
||||
|
||||
n = (((unsigned int)(*((*c)++))) << 24);
|
||||
n |= ((unsigned int)(*((*c)++)) << 16);
|
||||
n |= ((unsigned int)(*((*c)++)) << 8);
|
||||
n |= ((unsigned int)(*((*c)++)));
|
||||
return n;
|
||||
}
|
||||
|
||||
static void compress(unsigned int *iv, const uint8_t *data)
|
||||
{
|
||||
unsigned int a, b, c, d, e, f, g, h;
|
||||
unsigned int s0, s1;
|
||||
unsigned int t1, t2;
|
||||
unsigned int work_space[16];
|
||||
unsigned int n;
|
||||
unsigned int i;
|
||||
|
||||
a = iv[0]; b = iv[1]; c = iv[2]; d = iv[3];
|
||||
e = iv[4]; f = iv[5]; g = iv[6]; h = iv[7];
|
||||
|
||||
for (i = 0; i < 16; ++i) {
|
||||
n = BigEndian(&data);
|
||||
t1 = work_space[i] = n;
|
||||
t1 += h + Sigma1(e) + Ch(e, f, g) + k256[i];
|
||||
t2 = Sigma0(a) + Maj(a, b, c);
|
||||
h = g; g = f; f = e; e = d + t1;
|
||||
d = c; c = b; b = a; a = t1 + t2;
|
||||
}
|
||||
|
||||
for ( ; i < 64; ++i) {
|
||||
s0 = work_space[(i+1)&0x0f];
|
||||
s0 = sigma0(s0);
|
||||
s1 = work_space[(i+14)&0x0f];
|
||||
s1 = sigma1(s1);
|
||||
|
||||
t1 = work_space[i&0xf] += s0 + s1 + work_space[(i+9)&0xf];
|
||||
t1 += h + Sigma1(e) + Ch(e, f, g) + k256[i];
|
||||
t2 = Sigma0(a) + Maj(a, b, c);
|
||||
h = g; g = f; f = e; e = d + t1;
|
||||
d = c; c = b; b = a; a = t1 + t2;
|
||||
}
|
||||
|
||||
iv[0] += a; iv[1] += b; iv[2] += c; iv[3] += d;
|
||||
iv[4] += e; iv[5] += f; iv[6] += g; iv[7] += h;
|
||||
}
|
||||
74
lib/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/utils.c
Normal file
74
lib/NimBLE-Arduino/src/nimble/ext/tinycrypt/src/utils.c
Normal file
@@ -0,0 +1,74 @@
|
||||
/* utils.c - TinyCrypt platform-dependent run-time operations */
|
||||
|
||||
/*
|
||||
* Copyright (C) 2017 by Intel Corporation, All Rights Reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* - Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* - Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* - Neither the name of Intel Corporation nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
|
||||
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include "../include/tinycrypt/utils.h"
|
||||
#include "../include/tinycrypt/constants.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
#define MASK_TWENTY_SEVEN 0x1b
|
||||
|
||||
unsigned int _copy(uint8_t *to, unsigned int to_len,
|
||||
const uint8_t *from, unsigned int from_len)
|
||||
{
|
||||
if (from_len <= to_len) {
|
||||
(void)memcpy(to, from, from_len);
|
||||
return from_len;
|
||||
} else {
|
||||
return TC_CRYPTO_FAIL;
|
||||
}
|
||||
}
|
||||
|
||||
void _set(void *to, uint8_t val, unsigned int len)
|
||||
{
|
||||
(void)memset(to, val, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Doubles the value of a byte for values up to 127.
|
||||
*/
|
||||
uint8_t _double_byte(uint8_t a)
|
||||
{
|
||||
return ((a<<1) ^ ((a>>7) * MASK_TWENTY_SEVEN));
|
||||
}
|
||||
|
||||
int _compare(const uint8_t *a, const uint8_t *b, size_t size)
|
||||
{
|
||||
const uint8_t *tempa = a;
|
||||
const uint8_t *tempb = b;
|
||||
uint8_t result = 0;
|
||||
|
||||
for (unsigned int i = 0; i < size; i++) {
|
||||
result |= tempa[i] ^ tempb[i];
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef H_BLE_HW_
|
||||
#define H_BLE_HW_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "nimble/porting/nimble/include/syscfg/syscfg.h"
|
||||
|
||||
#if defined(ARCH_sim)
|
||||
#define BLE_USES_HW_WHITELIST (0)
|
||||
#else
|
||||
#define BLE_USES_HW_WHITELIST MYNEWT_VAL(BLE_HW_WHITELIST_ENABLE)
|
||||
#endif
|
||||
|
||||
/* Returns the number of hw whitelist elements */
|
||||
uint8_t ble_hw_whitelist_size(void);
|
||||
|
||||
/* Clear the whitelist */
|
||||
void ble_hw_whitelist_clear(void);
|
||||
|
||||
/* Remove a device from the hw whitelist */
|
||||
void ble_hw_whitelist_rmv(const uint8_t *addr, uint8_t addr_type);
|
||||
|
||||
/* Add a device to the hw whitelist */
|
||||
int ble_hw_whitelist_add(const uint8_t *addr, uint8_t addr_type);
|
||||
|
||||
/* Enable hw whitelisting */
|
||||
void ble_hw_whitelist_enable(void);
|
||||
|
||||
/* Enable hw whitelisting */
|
||||
void ble_hw_whitelist_disable(void);
|
||||
|
||||
/* Boolean function returning true if address matches a whitelist entry */
|
||||
int ble_hw_whitelist_match(void);
|
||||
|
||||
/* Encrypt data */
|
||||
struct ble_encryption_block;
|
||||
int ble_hw_encrypt_block(struct ble_encryption_block *ecb);
|
||||
|
||||
/* Random number generation */
|
||||
typedef void (*ble_rng_isr_cb_t)(uint8_t rnum);
|
||||
int ble_hw_rng_init(ble_rng_isr_cb_t cb, int bias);
|
||||
|
||||
/**
|
||||
* Start the random number generator
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int ble_hw_rng_start(void);
|
||||
|
||||
/**
|
||||
* Stop the random generator
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int ble_hw_rng_stop(void);
|
||||
|
||||
/**
|
||||
* Read the random number generator.
|
||||
*
|
||||
* @return uint8_t
|
||||
*/
|
||||
uint8_t ble_hw_rng_read(void);
|
||||
|
||||
/* Clear the resolving list*/
|
||||
void ble_hw_resolv_list_clear(void);
|
||||
|
||||
/* Add a device to the hw resolving list */
|
||||
int ble_hw_resolv_list_add(uint8_t *irk);
|
||||
|
||||
/* Remove a device from the hw resolving list */
|
||||
void ble_hw_resolv_list_rmv(int index);
|
||||
|
||||
/* Returns the size of the whitelist in HW */
|
||||
uint8_t ble_hw_resolv_list_size(void);
|
||||
|
||||
/* Enable the resolving list */
|
||||
void ble_hw_resolv_list_enable(void);
|
||||
|
||||
/* Disables resolving list devices */
|
||||
void ble_hw_resolv_list_disable(void);
|
||||
|
||||
/* Returns index of resolved address; -1 if not resolved */
|
||||
int ble_hw_resolv_list_match(void);
|
||||
|
||||
/* Returns public device address or -1 if not present */
|
||||
int ble_hw_get_public_addr(ble_addr_t *addr);
|
||||
|
||||
/* Returns random static address or -1 if not present */
|
||||
int ble_hw_get_static_addr(ble_addr_t *addr);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* H_BLE_HW_ */
|
||||
@@ -0,0 +1,584 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef H_BLE_LL_
|
||||
#define H_BLE_LL_
|
||||
|
||||
#include "nimble/porting/nimble/include/stats/stats.h"
|
||||
#include "nimble/porting/nimble/include/os/os_cputime.h"
|
||||
#include "nimble/nimble/include/nimble/nimble_opt.h"
|
||||
#include "nimble/nimble/include/nimble/nimble_npl.h"
|
||||
#include "ble_phy.h"
|
||||
|
||||
#ifdef MYNEWT
|
||||
#include "./ble_ll_ctrl.h"
|
||||
#include "hal/hal_system.h"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(OS_CPUTIME_FREQ) != 32768
|
||||
#error 32.768kHz clock required
|
||||
#endif
|
||||
|
||||
#if defined(MYNEWT) && MYNEWT_VAL(BLE_LL_VND_EVENT_ON_ASSERT)
|
||||
#ifdef NDEBUG
|
||||
#define BLE_LL_ASSERT(cond) (void(0))
|
||||
#else
|
||||
#define BLE_LL_ASSERT(cond) \
|
||||
if (!(cond)) { \
|
||||
if (hal_debugger_connected()) { \
|
||||
assert(0);\
|
||||
} else {\
|
||||
ble_ll_hci_ev_send_vendor_err(__FILE__, __LINE__); \
|
||||
while(1) {}\
|
||||
}\
|
||||
}
|
||||
#endif
|
||||
#else
|
||||
#define BLE_LL_ASSERT(cond) assert(cond)
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) || MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
|
||||
#define BLE_LL_BT5_PHY_SUPPORTED (1)
|
||||
#else
|
||||
#define BLE_LL_BT5_PHY_SUPPORTED (0)
|
||||
#endif
|
||||
|
||||
/* Controller revision. */
|
||||
#define BLE_LL_SUB_VERS_NR (0x0000)
|
||||
|
||||
/* Timing jitter as per spec is +/16 usecs */
|
||||
#define BLE_LL_JITTER_USECS (16)
|
||||
|
||||
/* Packet queue header definition */
|
||||
STAILQ_HEAD(ble_ll_pkt_q, os_mbuf_pkthdr);
|
||||
|
||||
/*
|
||||
* Global Link Layer data object. There is only one Link Layer data object
|
||||
* per controller although there may be many instances of the link layer state
|
||||
* machine running.
|
||||
*/
|
||||
struct ble_ll_obj
|
||||
{
|
||||
/* Supported features */
|
||||
uint64_t ll_supp_features;
|
||||
|
||||
/* Current Link Layer state */
|
||||
uint8_t ll_state;
|
||||
|
||||
/* Number of ACL data packets supported */
|
||||
uint8_t ll_num_acl_pkts;
|
||||
|
||||
/* ACL data packet size */
|
||||
uint16_t ll_acl_pkt_size;
|
||||
|
||||
/* Preferred PHY's */
|
||||
uint8_t ll_pref_tx_phys;
|
||||
uint8_t ll_pref_rx_phys;
|
||||
|
||||
/* Task event queue */
|
||||
struct ble_npl_eventq ll_evq;
|
||||
|
||||
/* Wait for response timer */
|
||||
struct hal_timer ll_wfr_timer;
|
||||
|
||||
/* Packet receive queue (and event). Holds received packets from PHY */
|
||||
struct ble_npl_event ll_rx_pkt_ev;
|
||||
struct ble_ll_pkt_q ll_rx_pkt_q;
|
||||
|
||||
/* Packet transmit queue */
|
||||
struct ble_npl_event ll_tx_pkt_ev;
|
||||
struct ble_ll_pkt_q ll_tx_pkt_q;
|
||||
|
||||
/* Data buffer overflow event */
|
||||
struct ble_npl_event ll_dbuf_overflow_ev;
|
||||
|
||||
/* Number of completed packets event */
|
||||
struct ble_npl_event ll_comp_pkt_ev;
|
||||
|
||||
/* HW error callout */
|
||||
struct ble_npl_callout ll_hw_err_timer;
|
||||
};
|
||||
extern struct ble_ll_obj g_ble_ll_data;
|
||||
|
||||
/* Link layer statistics */
|
||||
STATS_SECT_START(ble_ll_stats)
|
||||
STATS_SECT_ENTRY(hci_cmds)
|
||||
STATS_SECT_ENTRY(hci_cmd_errs)
|
||||
STATS_SECT_ENTRY(hci_events_sent)
|
||||
STATS_SECT_ENTRY(bad_ll_state)
|
||||
STATS_SECT_ENTRY(bad_acl_hdr)
|
||||
STATS_SECT_ENTRY(no_bufs)
|
||||
STATS_SECT_ENTRY(rx_adv_pdu_crc_ok)
|
||||
STATS_SECT_ENTRY(rx_adv_pdu_crc_err)
|
||||
STATS_SECT_ENTRY(rx_adv_bytes_crc_ok)
|
||||
STATS_SECT_ENTRY(rx_adv_bytes_crc_err)
|
||||
STATS_SECT_ENTRY(rx_data_pdu_crc_ok)
|
||||
STATS_SECT_ENTRY(rx_data_pdu_crc_err)
|
||||
STATS_SECT_ENTRY(rx_data_bytes_crc_ok)
|
||||
STATS_SECT_ENTRY(rx_data_bytes_crc_err)
|
||||
STATS_SECT_ENTRY(rx_adv_malformed_pkts)
|
||||
STATS_SECT_ENTRY(rx_adv_ind)
|
||||
STATS_SECT_ENTRY(rx_adv_direct_ind)
|
||||
STATS_SECT_ENTRY(rx_adv_nonconn_ind)
|
||||
STATS_SECT_ENTRY(rx_adv_ext_ind)
|
||||
STATS_SECT_ENTRY(rx_scan_reqs)
|
||||
STATS_SECT_ENTRY(rx_scan_rsps)
|
||||
STATS_SECT_ENTRY(rx_connect_reqs)
|
||||
STATS_SECT_ENTRY(rx_scan_ind)
|
||||
STATS_SECT_ENTRY(rx_aux_connect_rsp)
|
||||
STATS_SECT_ENTRY(adv_txg)
|
||||
STATS_SECT_ENTRY(adv_late_starts)
|
||||
STATS_SECT_ENTRY(adv_resched_pdu_fail)
|
||||
STATS_SECT_ENTRY(adv_drop_event)
|
||||
STATS_SECT_ENTRY(sched_state_conn_errs)
|
||||
STATS_SECT_ENTRY(sched_state_adv_errs)
|
||||
STATS_SECT_ENTRY(scan_starts)
|
||||
STATS_SECT_ENTRY(scan_stops)
|
||||
STATS_SECT_ENTRY(scan_req_txf)
|
||||
STATS_SECT_ENTRY(scan_req_txg)
|
||||
STATS_SECT_ENTRY(scan_rsp_txg)
|
||||
STATS_SECT_ENTRY(aux_missed_adv)
|
||||
STATS_SECT_ENTRY(aux_scheduled)
|
||||
STATS_SECT_ENTRY(aux_received)
|
||||
STATS_SECT_ENTRY(aux_fired_for_read)
|
||||
STATS_SECT_ENTRY(aux_allocated)
|
||||
STATS_SECT_ENTRY(aux_freed)
|
||||
STATS_SECT_ENTRY(aux_sched_cb)
|
||||
STATS_SECT_ENTRY(aux_conn_req_tx)
|
||||
STATS_SECT_ENTRY(aux_conn_rsp_tx)
|
||||
STATS_SECT_ENTRY(aux_conn_rsp_err)
|
||||
STATS_SECT_ENTRY(aux_scan_req_tx)
|
||||
STATS_SECT_ENTRY(aux_scan_rsp_err)
|
||||
STATS_SECT_ENTRY(aux_chain_cnt)
|
||||
STATS_SECT_ENTRY(aux_chain_err)
|
||||
STATS_SECT_ENTRY(aux_scan_drop)
|
||||
STATS_SECT_ENTRY(adv_evt_dropped)
|
||||
STATS_SECT_ENTRY(scan_timer_stopped)
|
||||
STATS_SECT_ENTRY(scan_timer_restarted)
|
||||
STATS_SECT_ENTRY(periodic_adv_drop_event)
|
||||
STATS_SECT_ENTRY(periodic_chain_drop_event)
|
||||
STATS_SECT_ENTRY(sync_event_failed)
|
||||
STATS_SECT_ENTRY(sync_received)
|
||||
STATS_SECT_ENTRY(sync_chain_failed)
|
||||
STATS_SECT_ENTRY(sync_missed_err)
|
||||
STATS_SECT_ENTRY(sync_crc_err)
|
||||
STATS_SECT_ENTRY(sync_rx_buf_err)
|
||||
STATS_SECT_ENTRY(sync_scheduled)
|
||||
STATS_SECT_ENTRY(sched_state_sync_errs)
|
||||
STATS_SECT_ENTRY(sched_invalid_pdu)
|
||||
STATS_SECT_END
|
||||
extern STATS_SECT_DECL(ble_ll_stats) ble_ll_stats;
|
||||
|
||||
/* States */
|
||||
#define BLE_LL_STATE_STANDBY (0)
|
||||
#define BLE_LL_STATE_ADV (1)
|
||||
#define BLE_LL_STATE_SCANNING (2)
|
||||
#define BLE_LL_STATE_INITIATING (3)
|
||||
#define BLE_LL_STATE_CONNECTION (4)
|
||||
#define BLE_LL_STATE_DTM (5)
|
||||
#define BLE_LL_STATE_SYNC (6)
|
||||
|
||||
/* LL Features */
|
||||
#define BLE_LL_FEAT_LE_ENCRYPTION (0x0000000001)
|
||||
#define BLE_LL_FEAT_CONN_PARM_REQ (0x0000000002)
|
||||
#define BLE_LL_FEAT_EXTENDED_REJ (0x0000000004)
|
||||
#define BLE_LL_FEAT_SLAVE_INIT (0x0000000008)
|
||||
#define BLE_LL_FEAT_LE_PING (0x0000000010)
|
||||
#define BLE_LL_FEAT_DATA_LEN_EXT (0x0000000020)
|
||||
#define BLE_LL_FEAT_LL_PRIVACY (0x0000000040)
|
||||
#define BLE_LL_FEAT_EXT_SCAN_FILT (0x0000000080)
|
||||
#define BLE_LL_FEAT_LE_2M_PHY (0x0000000100)
|
||||
#define BLE_LL_FEAT_STABLE_MOD_ID_TX (0x0000000200)
|
||||
#define BLE_LL_FEAT_STABLE_MOD_ID_RX (0x0000000400)
|
||||
#define BLE_LL_FEAT_LE_CODED_PHY (0x0000000800)
|
||||
#define BLE_LL_FEAT_EXT_ADV (0x0000001000)
|
||||
#define BLE_LL_FEAT_PERIODIC_ADV (0x0000002000)
|
||||
#define BLE_LL_FEAT_CSA2 (0x0000004000)
|
||||
#define BLE_LL_FEAT_LE_POWER_CLASS_1 (0x0000008000)
|
||||
#define BLE_LL_FEAT_MIN_USED_CHAN (0x0000010000)
|
||||
#define BLE_LL_FEAT_CTE_REQ (0x0000020000)
|
||||
#define BLE_LL_FEAT_CTE_RSP (0x0000040000)
|
||||
#define BLE_LL_FEAT_CTE_TX (0x0000080000)
|
||||
#define BLE_LL_FEAT_CTE_RX (0x0000100000)
|
||||
#define BLE_LL_FEAT_CTE_AOD (0x0000200000)
|
||||
#define BLE_LL_FEAT_CTE_AOA (0x0000400000)
|
||||
#define BLE_LL_FEAT_CTE_RECV (0x0000800000)
|
||||
#define BLE_LL_FEAT_SYNC_TRANS_SEND (0x0001000000)
|
||||
#define BLE_LL_FEAT_SYNC_TRANS_RECV (0x0002000000)
|
||||
#define BLE_LL_FEAT_SCA_UPDATE (0x0004000000)
|
||||
#define BLE_LL_FEAT_REM_PKEY (0x0008000000)
|
||||
#define BLE_LL_FEAT_CIS_MASTER (0x0010000000)
|
||||
#define BLE_LL_FEAT_CIS_SLAVE (0x0020000000)
|
||||
#define BLE_LL_FEAT_ISO_BROADCASTER (0x0040000000)
|
||||
#define BLE_LL_FEAT_SYNC_RECV (0x0080000000)
|
||||
#define BLE_LL_FEAT_ISO_HOST_SUPPORT (0x0100000000)
|
||||
#define BLE_LL_FEAT_POWER_CTRL_REQ (0x0200000000)
|
||||
#define BLE_LL_FEAT_POWER_CHANGE_IND (0x0400000000)
|
||||
#define BLE_LL_FEAT_PATH_LOSS_MON (0x0800000000)
|
||||
|
||||
/* This is initial mask, so if feature exchange will not happen,
|
||||
* but host will want to use this procedure, we will try. If not
|
||||
* succeed, feature bit will be cleared.
|
||||
* Look at LL Features above to find out what is allowed
|
||||
*/
|
||||
#define BLE_LL_CONN_INITIAL_FEATURES (0x00000022)
|
||||
#define BLE_LL_CONN_CLEAR_FEATURE(connsm, feature) (connsm->conn_features &= ~(feature))
|
||||
|
||||
/* All the features which can be controlled by the Host */
|
||||
#define BLE_LL_HOST_CONTROLLED_FEATURES (BLE_LL_FEAT_ISO_HOST_SUPPORT)
|
||||
|
||||
/* LL timing */
|
||||
#define BLE_LL_IFS (150) /* usecs */
|
||||
#define BLE_LL_MAFS (300) /* usecs */
|
||||
|
||||
/*
|
||||
* BLE LL device address. Note that element 0 of the array is the LSB and
|
||||
* is sent over the air first. Byte 5 is the MSB and is the last one sent over
|
||||
* the air.
|
||||
*/
|
||||
#define BLE_DEV_ADDR_LEN (6) /* bytes */
|
||||
|
||||
struct ble_dev_addr
|
||||
{
|
||||
uint8_t u8[BLE_DEV_ADDR_LEN];
|
||||
};
|
||||
|
||||
#define BLE_IS_DEV_ADDR_STATIC(addr) ((addr->u8[5] & 0xc0) == 0xc0)
|
||||
#define BLE_IS_DEV_ADDR_RESOLVABLE(addr) ((addr->u8[5] & 0xc0) == 0x40)
|
||||
#define BLE_IS_DEV_ADDR_UNRESOLVABLE(addr) ((addr->u8[5] & 0xc0) == 0x00)
|
||||
|
||||
/*
|
||||
* LL packet format
|
||||
*
|
||||
* -> Preamble (1/2 bytes)
|
||||
* -> Access Address (4 bytes)
|
||||
* -> PDU (2 to 257 octets)
|
||||
* -> CRC (3 bytes)
|
||||
*/
|
||||
#define BLE_LL_PREAMBLE_LEN (1)
|
||||
#define BLE_LL_ACC_ADDR_LEN (4)
|
||||
#define BLE_LL_CRC_LEN (3)
|
||||
#define BLE_LL_PDU_HDR_LEN (2)
|
||||
#define BLE_LL_MAX_PAYLOAD_LEN (255)
|
||||
#define BLE_LL_MIN_PDU_LEN (BLE_LL_PDU_HDR_LEN)
|
||||
#define BLE_LL_MAX_PDU_LEN ((BLE_LL_PDU_HDR_LEN) + (BLE_LL_MAX_PAYLOAD_LEN))
|
||||
#define BLE_LL_CRCINIT_ADV (0x555555)
|
||||
|
||||
/* Access address for advertising channels */
|
||||
#define BLE_ACCESS_ADDR_ADV (0x8E89BED6)
|
||||
|
||||
/*
|
||||
* Advertising PDU format:
|
||||
* -> 2 byte header
|
||||
* -> LSB contains pdu type, txadd and rxadd bits.
|
||||
* -> MSB contains length (6 bits). Length is length of payload. Does
|
||||
* not include the header length itself.
|
||||
* -> Payload (max 37 bytes)
|
||||
*/
|
||||
#define BLE_ADV_PDU_HDR_TYPE_MASK (0x0F)
|
||||
#define BLE_ADV_PDU_HDR_CHSEL_MASK (0x20)
|
||||
#define BLE_ADV_PDU_HDR_TXADD_MASK (0x40)
|
||||
#define BLE_ADV_PDU_HDR_RXADD_MASK (0x80)
|
||||
|
||||
/* Advertising channel PDU types */
|
||||
#define BLE_ADV_PDU_TYPE_ADV_IND (0)
|
||||
#define BLE_ADV_PDU_TYPE_ADV_DIRECT_IND (1)
|
||||
#define BLE_ADV_PDU_TYPE_ADV_NONCONN_IND (2)
|
||||
#define BLE_ADV_PDU_TYPE_SCAN_REQ (3)
|
||||
#define BLE_ADV_PDU_TYPE_SCAN_RSP (4)
|
||||
#define BLE_ADV_PDU_TYPE_CONNECT_IND (5)
|
||||
#define BLE_ADV_PDU_TYPE_ADV_SCAN_IND (6)
|
||||
#define BLE_ADV_PDU_TYPE_ADV_EXT_IND (7)
|
||||
#define BLE_ADV_PDU_TYPE_AUX_ADV_IND BLE_ADV_PDU_TYPE_ADV_EXT_IND
|
||||
#define BLE_ADV_PDU_TYPE_AUX_SCAN_RSP BLE_ADV_PDU_TYPE_ADV_EXT_IND
|
||||
#define BLE_ADV_PDU_TYPE_AUX_SYNC_IND BLE_ADV_PDU_TYPE_ADV_EXT_IND
|
||||
#define BLE_ADV_PDU_TYPE_AUX_CHAIN_IND BLE_ADV_PDU_TYPE_ADV_EXT_IND
|
||||
#define BLE_ADV_PDU_TYPE_AUX_CONNECT_REQ BLE_ADV_PDU_TYPE_CONNECT_IND
|
||||
#define BLE_ADV_PDU_TYPE_AUX_SCAN_REQ BLE_ADV_PDU_TYPE_SCAN_REQ
|
||||
#define BLE_ADV_PDU_TYPE_AUX_CONNECT_RSP (8)
|
||||
|
||||
/* Extended Header Length (6b) + AdvMode (2b) */
|
||||
#define BLE_LL_EXT_ADV_HDR_LEN (1)
|
||||
|
||||
#define BLE_LL_EXT_ADV_ADVA_BIT (0)
|
||||
#define BLE_LL_EXT_ADV_TARGETA_BIT (1)
|
||||
#define BLE_LL_EXT_ADV_CTE_INFO_BIT (2)
|
||||
#define BLE_LL_EXT_ADV_DATA_INFO_BIT (3)
|
||||
#define BLE_LL_EXT_ADV_AUX_PTR_BIT (4)
|
||||
#define BLE_LL_EXT_ADV_SYNC_INFO_BIT (5)
|
||||
#define BLE_LL_EXT_ADV_TX_POWER_BIT (6)
|
||||
|
||||
#define BLE_LL_EXT_ADV_FLAGS_SIZE (1)
|
||||
#define BLE_LL_EXT_ADV_ADVA_SIZE (6)
|
||||
#define BLE_LL_EXT_ADV_TARGETA_SIZE (6)
|
||||
#define BLE_LL_EXT_ADV_DATA_INFO_SIZE (2)
|
||||
#define BLE_LL_EXT_ADV_AUX_PTR_SIZE (3)
|
||||
#define BLE_LL_EXT_ADV_SYNC_INFO_SIZE (18)
|
||||
#define BLE_LL_EXT_ADV_TX_POWER_SIZE (1)
|
||||
|
||||
#define BLE_LL_EXT_ADV_MODE_NON_CONN (0x00)
|
||||
#define BLE_LL_EXT_ADV_MODE_CONN (0x01)
|
||||
#define BLE_LL_EXT_ADV_MODE_SCAN (0x02)
|
||||
|
||||
/* If Channel Selection Algorithm #2 is supported */
|
||||
#define BLE_ADV_PDU_HDR_CHSEL (0x20)
|
||||
|
||||
/*
|
||||
* TxAdd and RxAdd bit definitions. A 0 is a public address; a 1 is a
|
||||
* random address.
|
||||
*/
|
||||
#define BLE_ADV_PDU_HDR_TXADD_RAND (0x40)
|
||||
#define BLE_ADV_PDU_HDR_RXADD_RAND (0x80)
|
||||
|
||||
/*
|
||||
* Data Channel format
|
||||
*
|
||||
* -> Header (2 bytes)
|
||||
* -> LSB contains llid, nesn, sn and md
|
||||
* -> MSB contains length (8 bits)
|
||||
* -> Payload (0 to 251)
|
||||
* -> MIC (0 or 4 bytes)
|
||||
*/
|
||||
#define BLE_LL_DATA_HDR_LLID_MASK (0x03)
|
||||
#define BLE_LL_DATA_HDR_NESN_MASK (0x04)
|
||||
#define BLE_LL_DATA_HDR_SN_MASK (0x08)
|
||||
#define BLE_LL_DATA_HDR_MD_MASK (0x10)
|
||||
#define BLE_LL_DATA_HDR_RSRVD_MASK (0xE0)
|
||||
#define BLE_LL_DATA_PDU_MAX_PYLD (251)
|
||||
#define BLE_LL_DATA_MIC_LEN (4)
|
||||
|
||||
/* LLID definitions */
|
||||
#define BLE_LL_LLID_RSRVD (0)
|
||||
#define BLE_LL_LLID_DATA_FRAG (1)
|
||||
#define BLE_LL_LLID_DATA_START (2)
|
||||
#define BLE_LL_LLID_CTRL (3)
|
||||
|
||||
/*
|
||||
* CONNECT_REQ
|
||||
* -> InitA (6 bytes)
|
||||
* -> AdvA (6 bytes)
|
||||
* -> LLData (22 bytes)
|
||||
* -> Access address (4 bytes)
|
||||
* -> CRC initialize (3 bytes)
|
||||
* -> WinSize (1 byte)
|
||||
* -> WinOffset (2 bytes)
|
||||
* -> Interval (2 bytes)
|
||||
* -> Latency (2 bytes)
|
||||
* -> Timeout (2 bytes)
|
||||
* -> Channel Map (5 bytes)
|
||||
* -> Hop Increment (5 bits)
|
||||
* -> SCA (3 bits)
|
||||
*
|
||||
* InitA is the initiators public (TxAdd=0) or random (TxAdd=1) address.
|
||||
* AdvaA is the advertisers public (RxAdd=0) or random (RxAdd=1) address.
|
||||
* LLData contains connection request data.
|
||||
* aa: Link Layer's access address
|
||||
* crc_init: The CRC initialization value used for CRC calculation.
|
||||
* winsize: The transmit window size = winsize * 1.25 msecs
|
||||
* winoffset: The transmit window offset = winoffset * 1.25 msecs
|
||||
* interval: The connection interval = interval * 1.25 msecs.
|
||||
* latency: connection slave latency = latency
|
||||
* timeout: Connection supervision timeout = timeout * 10 msecs.
|
||||
* chanmap: contains channel mapping indicating used and unused data
|
||||
* channels. Only bits that are 1 are usable. LSB is channel 0.
|
||||
* hop_inc: Hop increment used for frequency hopping. Random value in
|
||||
* range of 5 to 16.
|
||||
*/
|
||||
#define BLE_CONNECT_REQ_LEN (34)
|
||||
#define BLE_CONNECT_REQ_PDU_LEN (BLE_CONNECT_REQ_LEN + BLE_LL_PDU_HDR_LEN)
|
||||
|
||||
#define BLE_SCAN_REQ_LEN (12)
|
||||
#define BLE_SCAN_RSP_MAX_LEN (37)
|
||||
#define BLE_SCAN_RSP_MAX_EXT_LEN (251)
|
||||
|
||||
#define BLE_LL_ADDR_SUBTYPE_IDENTITY (0)
|
||||
#define BLE_LL_ADDR_SUBTYPE_RPA (1)
|
||||
#define BLE_LL_ADDR_SUBTYPE_NRPA (2)
|
||||
|
||||
/*--- External API ---*/
|
||||
/* Initialize the Link Layer */
|
||||
void ble_ll_init(void);
|
||||
|
||||
/* Reset the Link Layer */
|
||||
int ble_ll_reset(void);
|
||||
|
||||
int ble_ll_is_valid_public_addr(const uint8_t *addr);
|
||||
|
||||
/* 'Boolean' function returning true if address is a valid random address */
|
||||
int ble_ll_is_valid_random_addr(const uint8_t *addr);
|
||||
|
||||
/*
|
||||
* Check if given own_addr_type is valid for current controller configuration
|
||||
* given the random address provided (when applicable)
|
||||
*/
|
||||
int ble_ll_is_valid_own_addr_type(uint8_t own_addr_type,
|
||||
const uint8_t *random_addr);
|
||||
|
||||
/* Calculate the amount of time in microseconds a PDU with payload length of
|
||||
* 'payload_len' will take to transmit on a PHY 'phy_mode'. */
|
||||
uint32_t ble_ll_pdu_tx_time_get(uint16_t payload_len, int phy_mode);
|
||||
|
||||
/* Calculate maximum octets of PDU payload which can be transmitted during
|
||||
* 'usecs' on a PHY 'phy_mode'. */
|
||||
uint16_t ble_ll_pdu_max_tx_octets_get(uint32_t usecs, int phy_mode);
|
||||
|
||||
/* Is this address a resolvable private address? */
|
||||
int ble_ll_is_rpa(const uint8_t *addr, uint8_t addr_type);
|
||||
|
||||
int ble_ll_addr_subtype(const uint8_t *addr, uint8_t addr_type);
|
||||
|
||||
/* Is this address an identity address? */
|
||||
int ble_ll_addr_is_id(uint8_t *addr, uint8_t addr_type);
|
||||
|
||||
/* Is 'addr' our device address? 'addr_type' is public (0) or random (!=0) */
|
||||
int ble_ll_is_our_devaddr(uint8_t *addr, int addr_type);
|
||||
|
||||
/* Get identity address 'addr_type' is public (0) or random (!=0) */
|
||||
uint8_t *ble_ll_get_our_devaddr(uint8_t addr_type);
|
||||
|
||||
/**
|
||||
* Called to put a packet on the Link Layer transmit packet queue.
|
||||
*
|
||||
* @param txpdu Pointer to transmit packet
|
||||
*/
|
||||
void ble_ll_acl_data_in(struct os_mbuf *txpkt);
|
||||
|
||||
/**
|
||||
* Allocates mbuf for received PDU
|
||||
*
|
||||
* This allocated mbuf (may be chained if necessary) that has capacity large
|
||||
* enough to store received PDU of given length. It does not set mbufs length
|
||||
* as this has to be done by PHY when copying data.
|
||||
*
|
||||
* @param len Length of PDU, including PDU header and excluding MIC (if encrypted)
|
||||
*
|
||||
* @return mbuf large enough to store received PDU on success
|
||||
* NULL on failure (oom)
|
||||
*/
|
||||
struct os_mbuf *ble_ll_rxpdu_alloc(uint16_t len);
|
||||
|
||||
/* Tell the Link Layer there has been a data buffer overflow */
|
||||
void ble_ll_data_buffer_overflow(void);
|
||||
|
||||
/* Tell the link layer there has been a hardware error */
|
||||
void ble_ll_hw_error(void);
|
||||
|
||||
/*--- PHY interfaces ---*/
|
||||
struct ble_mbuf_hdr;
|
||||
|
||||
/* Called by the PHY when a packet has started */
|
||||
int ble_ll_rx_start(uint8_t *rxbuf, uint8_t chan, struct ble_mbuf_hdr *hdr);
|
||||
|
||||
/* Called by the PHY when a packet reception ends */
|
||||
int ble_ll_rx_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr);
|
||||
|
||||
/* Helper callback to tx mbuf using ble_phy_tx() */
|
||||
uint8_t ble_ll_tx_mbuf_pducb(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte);
|
||||
uint8_t ble_ll_tx_flat_mbuf_pducb(uint8_t *dptr, void *pducb_arg, uint8_t *hdr_byte);
|
||||
|
||||
/*--- Controller API ---*/
|
||||
void ble_ll_mbuf_init(struct os_mbuf *m, uint8_t pdulen, uint8_t hdr);
|
||||
|
||||
/* Set the link layer state */
|
||||
void ble_ll_state_set(uint8_t ll_state);
|
||||
|
||||
/* Get the link layer state */
|
||||
uint8_t ble_ll_state_get(void);
|
||||
|
||||
/* Send an event to LL task */
|
||||
void ble_ll_event_send(struct ble_npl_event *ev);
|
||||
|
||||
/* Hand received pdu's to LL task */
|
||||
void ble_ll_rx_pdu_in(struct os_mbuf *rxpdu);
|
||||
|
||||
/*
|
||||
* Set public address
|
||||
*
|
||||
* This can be used to set controller public address from vendor specific storage,
|
||||
* usually should be done in hal_bsp_init().
|
||||
* Shall be *only* called before LL is initialized, i.e. before sysinit stage.
|
||||
*/
|
||||
int ble_ll_set_public_addr(const uint8_t *addr);
|
||||
|
||||
/* Set random address */
|
||||
int ble_ll_set_random_addr(const uint8_t *cmdbuf, uint8_t len, bool hci_adv_ext);
|
||||
|
||||
/* Wait for response timer expiration callback */
|
||||
void ble_ll_wfr_timer_exp(void *arg);
|
||||
|
||||
/* Read set of features supported by the Link Layer */
|
||||
uint64_t ble_ll_read_supp_features(void);
|
||||
|
||||
/* Set host supported features */
|
||||
int ble_ll_set_host_feat(const uint8_t *cmdbuf, uint8_t len);
|
||||
|
||||
/* Read set of states supported by the Link Layer */
|
||||
uint64_t ble_ll_read_supp_states(void);
|
||||
|
||||
/* Check if octets and time are valid. Returns 0 if not valid */
|
||||
int ble_ll_chk_txrx_octets(uint16_t octets);
|
||||
int ble_ll_chk_txrx_time(uint16_t time);
|
||||
|
||||
/* Random numbers */
|
||||
int ble_ll_rand_init(void);
|
||||
void ble_ll_rand_sample(uint8_t rnum);
|
||||
int ble_ll_rand_data_get(uint8_t *buf, uint8_t len);
|
||||
void ble_ll_rand_prand_get(uint8_t *prand);
|
||||
int ble_ll_rand_start(void);
|
||||
|
||||
static inline int
|
||||
ble_ll_get_addr_type(uint8_t txrxflag)
|
||||
{
|
||||
if (txrxflag) {
|
||||
return BLE_HCI_ADV_OWN_ADDR_RANDOM;
|
||||
}
|
||||
return BLE_HCI_ADV_OWN_ADDR_PUBLIC;
|
||||
}
|
||||
|
||||
/* Convert usecs to ticks and round up to nearest tick */
|
||||
static inline uint32_t
|
||||
ble_ll_usecs_to_ticks_round_up(uint32_t usecs)
|
||||
{
|
||||
return os_cputime_usecs_to_ticks(usecs + 30);
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
|
||||
/* LTK 0x4C68384139F574D836BCF34E9DFB01BF */
|
||||
extern const uint8_t g_bletest_LTK[];
|
||||
extern uint16_t g_bletest_EDIV;
|
||||
extern uint64_t g_bletest_RAND;
|
||||
extern uint64_t g_bletest_SKDm;
|
||||
extern uint64_t g_bletest_SKDs;
|
||||
extern uint32_t g_bletest_IVm;
|
||||
extern uint32_t g_bletest_IVs;
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_DTM)
|
||||
void ble_ll_dtm_init(void);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* H_LL_ */
|
||||
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef H_BLE_LL_ADV_
|
||||
#define H_BLE_LL_ADV_
|
||||
|
||||
#include "nimble/porting/nimble/include/syscfg/syscfg.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* ADV event timing
|
||||
* T_advEvent = advInterval + advDelay
|
||||
*
|
||||
* advInterval: increments of 625 usecs
|
||||
* advDelay: RAND[0, 10] msecs
|
||||
*
|
||||
*/
|
||||
#define BLE_LL_ADV_ITVL (625) /* usecs */
|
||||
#define BLE_LL_ADV_ITVL_MIN (32) /* units */
|
||||
#define BLE_LL_ADV_ITVL_MAX (16384) /* units */
|
||||
#define BLE_LL_ADV_ITVL_MS_MIN (20) /* msecs */
|
||||
#define BLE_LL_ADV_ITVL_MS_MAX (10240) /* msecs */
|
||||
#define BLE_LL_ADV_ITVL_SCAN_MIN (160) /* units */
|
||||
#define BLE_LL_ADV_ITVL_SCAN_MS_MIN (100) /* msecs */
|
||||
#define BLE_LL_ADV_ITVL_NONCONN_MS_MIN (100) /* msecs */
|
||||
#define BLE_LL_ADV_DELAY_MS_MIN (0) /* msecs */
|
||||
#define BLE_LL_ADV_DELAY_MS_MAX (10) /* msecs */
|
||||
#define BLE_LL_ADV_PDU_ITVL_LD_MS_MAX (10) /* msecs */
|
||||
#define BLE_LL_ADV_PDU_ITVL_HD_MS_MAX (3750) /* usecs */
|
||||
#define BLE_LL_ADV_STATE_HD_MAX (1280) /* msecs */
|
||||
#define BLE_LL_ADV_PERIODIC_ITVL (1250) /* usecs */
|
||||
|
||||
/* Maximum advertisement data length */
|
||||
#define BLE_ADV_LEGACY_DATA_MAX_LEN (31)
|
||||
#define BLE_ADV_LEGACY_MAX_PKT_LEN (37)
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
|
||||
#define BLE_ADV_DATA_MAX_LEN MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE)
|
||||
#else
|
||||
#define BLE_ADV_DATA_MAX_LEN BLE_ADV_LEGACY_DATA_MAX_LEN
|
||||
#endif
|
||||
|
||||
/*
|
||||
* ADV_IND
|
||||
* -> AdvA (6 bytes)
|
||||
* -> AdvData (0 - 31 bytes)
|
||||
*
|
||||
* The advertising address (AdvA) is a public address (TxAdd=0) or random
|
||||
* address (TxAdd = 1)
|
||||
*/
|
||||
#define BLE_ADV_IND_MIN_LEN (6)
|
||||
#define BLE_ADV_IND_MAX_LEN (37)
|
||||
|
||||
/*
|
||||
* ADV_DIRECT_IND
|
||||
* -> AdvA (6 bytes)
|
||||
* -> InitA (6 bytes)
|
||||
*
|
||||
* AdvA is the advertisers public address (TxAdd=0) or random address
|
||||
* (TxAdd = 1).
|
||||
*
|
||||
* InitA is the initiators public or random address. This is the address
|
||||
* to which this packet is addressed.
|
||||
*
|
||||
*/
|
||||
#define BLE_ADV_DIRECT_IND_LEN (12)
|
||||
|
||||
/*
|
||||
* ADV_NONCONN_IND
|
||||
* -> AdvA (6 bytes)
|
||||
* -> AdvData (0 - 31 bytes)
|
||||
*
|
||||
* The advertising address (AdvA) is a public address (TxAdd=0) or random
|
||||
* address (TxAdd = 1)
|
||||
*
|
||||
*/
|
||||
#define BLE_ADV_NONCONN_IND_MIN_LEN (6)
|
||||
#define BLE_ADV_NONCONN_IND_MAX_LEN (37)
|
||||
|
||||
/*
|
||||
* ADV_SCAN_IND
|
||||
* -> AdvA (6 bytes)
|
||||
* -> AdvData (0 - 31 bytes)
|
||||
*
|
||||
* The advertising address (AdvA) is a public address (TxAdd=0) or random
|
||||
* address (TxAdd = 1)
|
||||
*
|
||||
*/
|
||||
#define BLE_ADV_SCAN_IND_MIN_LEN (6)
|
||||
#define BLE_ADV_SCAN_IND_MAX_LEN (37)
|
||||
|
||||
/*---- HCI ----*/
|
||||
struct ble_ll_adv_sm;
|
||||
struct ble_ll_conn_sm;
|
||||
|
||||
/* Start an advertiser */
|
||||
int ble_ll_adv_start_req(uint8_t adv_chanmask, uint8_t adv_type,
|
||||
uint8_t *init_addr, uint16_t adv_itvl, void *handle);
|
||||
|
||||
/* Start or stop advertising */
|
||||
int ble_ll_hci_adv_set_enable(const uint8_t *cmdbuf, uint8_t len);
|
||||
|
||||
/* Set legacy advertising data */
|
||||
int ble_ll_hci_set_adv_data(const uint8_t *cmdbuf, uint8_t len);
|
||||
|
||||
/* Set scan response data */
|
||||
int ble_ll_hci_set_scan_rsp_data(const uint8_t *cmd, uint8_t cmd_len);
|
||||
|
||||
/* Set advertising parameters */
|
||||
int ble_ll_adv_set_adv_params(const uint8_t *cmdbuf, uint8_t len);
|
||||
|
||||
/* Read advertising channel power */
|
||||
int ble_ll_adv_read_txpwr(uint8_t *rspbuf, uint8_t *rsplen);
|
||||
|
||||
/*---- API used by BLE LL ----*/
|
||||
/* Send the connection complete event */
|
||||
void ble_ll_adv_send_conn_comp_ev(struct ble_ll_conn_sm *connsm,
|
||||
struct ble_mbuf_hdr *rxhdr);
|
||||
|
||||
/* Returns local resolvable private address */
|
||||
uint8_t *ble_ll_adv_get_local_rpa(struct ble_ll_adv_sm *advsm);
|
||||
|
||||
/* Returns peer resolvable private address */
|
||||
uint8_t *ble_ll_adv_get_peer_rpa(struct ble_ll_adv_sm *advsm);
|
||||
|
||||
/* Called to initialize advertising functionality. */
|
||||
void ble_ll_adv_init(void);
|
||||
|
||||
/* Called when LL wait for response timer expires in advertising state */
|
||||
void ble_ll_adv_wfr_timer_exp(void);
|
||||
|
||||
/* Called to reset the advertiser. */
|
||||
void ble_ll_adv_reset(void);
|
||||
|
||||
/* Called on rx pdu start when in advertising state */
|
||||
int ble_ll_adv_rx_isr_start(uint8_t pdu_type);
|
||||
|
||||
/* Called on rx pdu end when in advertising state */
|
||||
int ble_ll_adv_rx_isr_end(uint8_t pdu_type, struct os_mbuf *rxpdu, int crcok);
|
||||
|
||||
/* Processes received packets at the link layer task */
|
||||
void ble_ll_adv_rx_pkt_in(uint8_t ptype, uint8_t *rxbuf,
|
||||
struct ble_mbuf_hdr *hdr);
|
||||
|
||||
/* Boolean function denoting whether or not the whitelist can be changed */
|
||||
int ble_ll_adv_can_chg_whitelist(void);
|
||||
|
||||
/*
|
||||
* Called when an advertising event has been removed from the scheduler
|
||||
* without being run.
|
||||
*/
|
||||
void ble_ll_adv_event_rmvd_from_sched(struct ble_ll_adv_sm *advsm);
|
||||
|
||||
/*
|
||||
* Called when a periodic event has been removed from the scheduler
|
||||
* without being run.
|
||||
*/
|
||||
void ble_ll_adv_periodic_rmvd_from_sched(struct ble_ll_adv_sm *advsm);
|
||||
|
||||
/* Called to halt currently running advertising event */
|
||||
void ble_ll_adv_halt(void);
|
||||
|
||||
/* Called to determine if advertising is enabled */
|
||||
uint8_t ble_ll_adv_enabled(void);
|
||||
|
||||
int ble_ll_adv_hci_set_random_addr(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_adv_set_random_addr(const uint8_t *addr, uint8_t instance);
|
||||
int ble_ll_adv_remove(const uint8_t *addr, uint8_t len);
|
||||
int ble_ll_adv_clear_all(void);
|
||||
int ble_ll_adv_ext_set_param(const uint8_t *cmdbuf, uint8_t len,
|
||||
uint8_t *rspbuf, uint8_t *rsplen);
|
||||
int ble_ll_adv_ext_set_adv_data(const uint8_t *cmdbuf, uint8_t cmdlen);
|
||||
int ble_ll_adv_ext_set_scan_rsp(const uint8_t *cmdbuf, uint8_t cmdlen);
|
||||
int ble_ll_adv_ext_set_enable(const uint8_t *cmdbuf, uint8_t len);
|
||||
|
||||
int ble_ll_adv_periodic_set_param(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_adv_periodic_set_data(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_adv_periodic_enable(const uint8_t *cmdbuf, uint8_t len);
|
||||
|
||||
int ble_ll_adv_periodic_set_info_transfer(const uint8_t *cmdbuf, uint8_t len,
|
||||
uint8_t *rspbuf, uint8_t *rsplen);
|
||||
|
||||
/* Called to notify adv code about RPA rotation */
|
||||
void ble_ll_adv_rpa_timeout(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* H_BLE_LL_ADV_ */
|
||||
@@ -0,0 +1,425 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef H_BLE_LL_CONN_
|
||||
#define H_BLE_LL_CONN_
|
||||
|
||||
#include "nimble/porting/nimble/include/os/os.h"
|
||||
#include "nimble/nimble/include/nimble/ble.h"
|
||||
#include "nimble/nimble/include/nimble/hci_common.h"
|
||||
#include "nimble/nimble/include/nimble/nimble_npl.h"
|
||||
#include "ble_ll_sched.h"
|
||||
#include "ble_ll_ctrl.h"
|
||||
#include "ble_phy.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Roles */
|
||||
#define BLE_LL_CONN_ROLE_NONE (0)
|
||||
#define BLE_LL_CONN_ROLE_MASTER (1)
|
||||
#define BLE_LL_CONN_ROLE_SLAVE (2)
|
||||
|
||||
/* Connection states */
|
||||
#define BLE_LL_CONN_STATE_IDLE (0)
|
||||
#define BLE_LL_CONN_STATE_CREATED (1)
|
||||
#define BLE_LL_CONN_STATE_ESTABLISHED (2)
|
||||
|
||||
/* Channel map size */
|
||||
#define BLE_LL_CONN_CHMAP_LEN (5)
|
||||
|
||||
/* Definitions for source clock accuracy */
|
||||
#define BLE_MASTER_SCA_251_500_PPM (0)
|
||||
#define BLE_MASTER_SCA_151_250_PPM (1)
|
||||
#define BLE_MASTER_SCA_101_150_PPM (2)
|
||||
#define BLE_MASTER_SCA_76_100_PPM (3)
|
||||
#define BLE_MASTER_SCA_51_75_PPM (4)
|
||||
#define BLE_MASTER_SCA_31_50_PPM (5)
|
||||
#define BLE_MASTER_SCA_21_30_PPM (6)
|
||||
#define BLE_MASTER_SCA_0_20_PPM (7)
|
||||
|
||||
/* Definition for RSSI when the RSSI is unknown */
|
||||
#define BLE_LL_CONN_UNKNOWN_RSSI (127)
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
|
||||
/*
|
||||
* Encryption states for a connection
|
||||
*
|
||||
* NOTE: the states are ordered so that we can check to see if the state
|
||||
* is greater than ENCRYPTED. If so, it means that the start or pause
|
||||
* encryption procedure is running and we should not send data pdu's.
|
||||
*/
|
||||
enum conn_enc_state {
|
||||
CONN_ENC_S_UNENCRYPTED = 1,
|
||||
CONN_ENC_S_ENCRYPTED,
|
||||
CONN_ENC_S_ENC_RSP_WAIT,
|
||||
CONN_ENC_S_PAUSE_ENC_RSP_WAIT,
|
||||
CONN_ENC_S_PAUSED,
|
||||
CONN_ENC_S_START_ENC_REQ_WAIT,
|
||||
CONN_ENC_S_START_ENC_RSP_WAIT,
|
||||
CONN_ENC_S_LTK_REQ_WAIT,
|
||||
CONN_ENC_S_LTK_NEG_REPLY
|
||||
};
|
||||
|
||||
/*
|
||||
* Note that the LTK is the key, the SDK is the plain text, and the
|
||||
* session key is the cipher text portion of the encryption block.
|
||||
*
|
||||
* NOTE: we have intentionally violated the specification by making the
|
||||
* transmit and receive packet counters 32-bits as opposed to 39 (as per the
|
||||
* specification). We do this to save code space, ram and calculation time. The
|
||||
* only drawback is that any encrypted connection that sends more than 2^32
|
||||
* packets will suffer a MIC failure and thus be disconnected.
|
||||
*/
|
||||
struct ble_ll_conn_enc_data
|
||||
{
|
||||
uint8_t enc_state;
|
||||
uint8_t tx_encrypted;
|
||||
uint16_t enc_div;
|
||||
uint32_t tx_pkt_cntr;
|
||||
uint32_t rx_pkt_cntr;
|
||||
uint64_t host_rand_num;
|
||||
uint8_t iv[8];
|
||||
struct ble_encryption_block enc_block;
|
||||
};
|
||||
#endif
|
||||
|
||||
/* Connection state machine flags. */
|
||||
union ble_ll_conn_sm_flags {
|
||||
struct {
|
||||
uint32_t pkt_rxd:1;
|
||||
uint32_t terminate_ind_txd:1;
|
||||
uint32_t terminate_ind_rxd:1;
|
||||
uint32_t terminate_ind_rxd_acked:1;
|
||||
uint32_t allow_slave_latency:1;
|
||||
uint32_t slave_set_last_anchor:1;
|
||||
uint32_t awaiting_host_reply:1;
|
||||
uint32_t terminate_started:1;
|
||||
uint32_t conn_update_sched:1;
|
||||
uint32_t host_expects_upd_event:1;
|
||||
uint32_t version_ind_sent:1;
|
||||
uint32_t rxd_version_ind:1;
|
||||
uint32_t chanmap_update_scheduled:1;
|
||||
uint32_t conn_empty_pdu_txd:1;
|
||||
uint32_t last_txd_md:1;
|
||||
uint32_t conn_req_txd:1;
|
||||
uint32_t send_ltk_req:1;
|
||||
uint32_t encrypted:1;
|
||||
uint32_t encrypt_chg_sent:1;
|
||||
uint32_t le_ping_supp:1;
|
||||
uint32_t csa2_supp:1;
|
||||
uint32_t host_phy_update: 1;
|
||||
uint32_t phy_update_sched: 1;
|
||||
uint32_t ctrlr_phy_update: 1;
|
||||
uint32_t phy_update_event: 1;
|
||||
uint32_t peer_phy_update: 1; /* XXX:combine with ctrlr udpate bit? */
|
||||
uint32_t aux_conn_req: 1;
|
||||
uint32_t rxd_features:1;
|
||||
uint32_t pending_hci_rd_features:1;
|
||||
uint32_t pending_initiate_dle:1;
|
||||
} cfbit;
|
||||
uint32_t conn_flags;
|
||||
} __attribute__((packed));
|
||||
|
||||
/**
|
||||
* Structure used for PHY data inside a connection.
|
||||
*
|
||||
* NOTE: the new phy's are the phys we will change to when a phy update
|
||||
* procedure is ongoing and the event counter hits the instant.
|
||||
*
|
||||
* tx_phy_mode: chip specific phy mode for tx
|
||||
* rx_phy_mode: chip specific phy mode for rx
|
||||
* cur_tx_phy: value denoting current tx_phy (not a bitmask!)
|
||||
* cur_rx_phy: value denoting current rx phy (not a bitmask!)
|
||||
* new_tx_phy: value denoting new tx_phy (not a bitmask!)
|
||||
* new_rx_phy: value denoting new rx phy (not a bitmask!)
|
||||
* req_pref_tx_phy: tx phy sent in a phy request (may be different than host)
|
||||
* req_pref_rx_phy: rx phy sent in a phy request (may be different than host)
|
||||
* host_pref_tx_phys: bitmask of preferred transmit PHYs sent by host
|
||||
* host_pref_rx_phys: bitmask of preferred receive PHYs sent by host
|
||||
* phy_options: preferred phy options for coded phy
|
||||
*/
|
||||
struct ble_ll_conn_phy_data
|
||||
{
|
||||
uint32_t tx_phy_mode: 2;
|
||||
uint32_t rx_phy_mode: 2;
|
||||
uint32_t cur_tx_phy: 2;
|
||||
uint32_t cur_rx_phy: 2;
|
||||
uint32_t new_tx_phy: 2;
|
||||
uint32_t new_rx_phy: 2;
|
||||
uint32_t host_pref_tx_phys_mask: 3;
|
||||
uint32_t host_pref_rx_phys_mask: 3;
|
||||
uint32_t req_pref_tx_phys_mask: 3;
|
||||
uint32_t req_pref_rx_phys_mask: 3;
|
||||
uint32_t phy_options: 2;
|
||||
} __attribute__((packed));
|
||||
|
||||
#define CONN_CUR_TX_PHY_MASK(csm) (1 << ((csm)->phy_data.cur_tx_phy - 1))
|
||||
#define CONN_CUR_RX_PHY_MASK(csm) (1 << ((csm)->phy_data.cur_rx_phy - 1))
|
||||
|
||||
struct hci_conn_update
|
||||
{
|
||||
uint16_t handle;
|
||||
uint16_t conn_itvl_min;
|
||||
uint16_t conn_itvl_max;
|
||||
uint16_t conn_latency;
|
||||
uint16_t supervision_timeout;
|
||||
uint16_t min_ce_len;
|
||||
uint16_t max_ce_len;
|
||||
};
|
||||
|
||||
struct hci_ext_conn_params
|
||||
{
|
||||
uint16_t scan_itvl;
|
||||
uint16_t scan_window;
|
||||
uint16_t conn_itvl_min;
|
||||
uint16_t conn_itvl_max;
|
||||
uint16_t conn_latency;
|
||||
uint16_t supervision_timeout;
|
||||
uint16_t min_ce_len;
|
||||
uint16_t max_ce_len;
|
||||
};
|
||||
|
||||
struct hci_ext_create_conn
|
||||
{
|
||||
uint8_t filter_policy;
|
||||
uint8_t own_addr_type;
|
||||
uint8_t peer_addr_type;
|
||||
uint8_t peer_addr[BLE_DEV_ADDR_LEN];
|
||||
uint8_t init_phy_mask;
|
||||
struct hci_ext_conn_params params[3];
|
||||
};
|
||||
|
||||
/* Connection state machine */
|
||||
struct ble_ll_conn_sm
|
||||
{
|
||||
/* Connection state machine flags */
|
||||
union ble_ll_conn_sm_flags csmflags;
|
||||
|
||||
/* Current connection handle, state and role */
|
||||
uint16_t conn_handle;
|
||||
uint8_t conn_state;
|
||||
uint8_t conn_role; /* Can possibly be 1 bit */
|
||||
|
||||
/* RSSI */
|
||||
int8_t conn_rssi;
|
||||
|
||||
/* For privacy */
|
||||
int8_t rpa_index;
|
||||
|
||||
/* Connection data length management */
|
||||
uint8_t max_tx_octets;
|
||||
uint8_t max_rx_octets;
|
||||
uint8_t rem_max_tx_octets;
|
||||
uint8_t rem_max_rx_octets;
|
||||
uint8_t eff_max_tx_octets;
|
||||
uint8_t eff_max_rx_octets;
|
||||
uint16_t max_tx_time;
|
||||
uint16_t max_rx_time;
|
||||
uint16_t rem_max_tx_time;
|
||||
uint16_t rem_max_rx_time;
|
||||
uint16_t eff_max_tx_time;
|
||||
uint16_t eff_max_rx_time;
|
||||
uint8_t max_tx_octets_phy_mode[BLE_PHY_NUM_MODE];
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
|
||||
uint16_t host_req_max_tx_time;
|
||||
#endif
|
||||
|
||||
#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
|
||||
struct ble_ll_conn_phy_data phy_data;
|
||||
uint16_t phy_instant;
|
||||
uint8_t phy_tx_transition;
|
||||
#endif
|
||||
|
||||
/* Used to calculate data channel index for connection */
|
||||
uint8_t chanmap[BLE_LL_CONN_CHMAP_LEN];
|
||||
uint8_t req_chanmap[BLE_LL_CONN_CHMAP_LEN];
|
||||
uint16_t chanmap_instant;
|
||||
uint16_t channel_id; /* TODO could be union with hop and last chan used */
|
||||
uint8_t hop_inc;
|
||||
uint8_t data_chan_index;
|
||||
uint8_t last_unmapped_chan;
|
||||
uint8_t num_used_chans;
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_STRICT_CONN_SCHEDULING)
|
||||
uint8_t period_occ_mask; /* mask: period 0 = 0x01, period 3 = 0x08 */
|
||||
#endif
|
||||
|
||||
/* Ack/Flow Control */
|
||||
uint8_t tx_seqnum; /* note: can be 1 bit */
|
||||
uint8_t next_exp_seqnum; /* note: can be 1 bit */
|
||||
uint8_t cons_rxd_bad_crc; /* note: can be 1 bit */
|
||||
uint8_t last_rxd_sn; /* note: cant be 1 bit given current code */
|
||||
uint8_t last_rxd_hdr_byte; /* note: possibly can make 1 bit since we
|
||||
only use the MD bit now */
|
||||
|
||||
/* connection event mgmt */
|
||||
uint8_t reject_reason;
|
||||
uint8_t host_reply_opcode;
|
||||
uint8_t master_sca;
|
||||
uint8_t tx_win_size;
|
||||
uint8_t cur_ctrl_proc;
|
||||
uint8_t disconnect_reason;
|
||||
uint8_t rxd_disconnect_reason;
|
||||
uint8_t vers_nr;
|
||||
uint8_t conn_features;
|
||||
uint8_t remote_features[7];
|
||||
uint16_t pending_ctrl_procs;
|
||||
uint16_t event_cntr;
|
||||
uint16_t completed_pkts;
|
||||
uint16_t comp_id;
|
||||
uint16_t sub_vers_nr;
|
||||
uint16_t auth_pyld_tmo; /* could be ifdef'd. 10 msec units */
|
||||
|
||||
uint32_t access_addr;
|
||||
uint32_t crcinit; /* only low 24 bits used */
|
||||
/* XXX: do we need ce_end_time? Cant this be sched end time? */
|
||||
uint32_t ce_end_time; /* cputime at which connection event should end */
|
||||
uint32_t terminate_timeout;
|
||||
uint32_t last_scheduled;
|
||||
|
||||
/* Connection timing */
|
||||
uint16_t conn_itvl;
|
||||
uint16_t slave_latency;
|
||||
uint16_t supervision_tmo;
|
||||
uint16_t min_ce_len;
|
||||
uint16_t max_ce_len;
|
||||
uint16_t tx_win_off;
|
||||
uint32_t anchor_point;
|
||||
uint8_t anchor_point_usecs; /* XXX: can this be uint8_t ?*/
|
||||
uint8_t conn_itvl_usecs;
|
||||
uint32_t conn_itvl_ticks;
|
||||
uint32_t last_anchor_point; /* Slave only */
|
||||
uint32_t slave_cur_tx_win_usecs;
|
||||
uint32_t slave_cur_window_widening;
|
||||
uint32_t last_rxd_pdu_cputime; /* Used exclusively for supervision timer */
|
||||
|
||||
/*
|
||||
* Used to mark that identity address was used as InitA
|
||||
*/
|
||||
uint8_t inita_identity_used;
|
||||
|
||||
/* address information */
|
||||
uint8_t own_addr_type;
|
||||
uint8_t peer_addr_type;
|
||||
uint8_t peer_addr[BLE_DEV_ADDR_LEN];
|
||||
|
||||
/*
|
||||
* XXX: TODO. Could save memory. Have single event at LL and put these
|
||||
* on a singly linked list. Only would need list pointer here.
|
||||
*/
|
||||
/* Connection end event */
|
||||
struct ble_npl_event conn_ev_end;
|
||||
|
||||
/* Packet transmit queue */
|
||||
struct os_mbuf *cur_tx_pdu;
|
||||
STAILQ_HEAD(conn_txq_head, os_mbuf_pkthdr) conn_txq;
|
||||
|
||||
/* List entry for active/free connection pools */
|
||||
union {
|
||||
SLIST_ENTRY(ble_ll_conn_sm) act_sle;
|
||||
STAILQ_ENTRY(ble_ll_conn_sm) free_stqe;
|
||||
};
|
||||
|
||||
/* LL control procedure response timer */
|
||||
struct ble_npl_callout ctrl_proc_rsp_timer;
|
||||
|
||||
/* For scheduling connections */
|
||||
struct ble_ll_sched_item conn_sch;
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING)
|
||||
struct ble_npl_callout auth_pyld_timer;
|
||||
#endif
|
||||
|
||||
/*
|
||||
* XXX: a note on all these structures for control procedures. First off,
|
||||
* all of these need to be ifdef'd to save memory. Another thing to
|
||||
* consider is this: since most control procedures can only run when no
|
||||
* others are running, can I use just one structure (a union)? Should I
|
||||
* allocate these from a pool? Not sure what to do. For now, I just use
|
||||
* a large chunk of memory per connection.
|
||||
*/
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
|
||||
struct ble_ll_conn_enc_data enc_data;
|
||||
#endif
|
||||
/*
|
||||
* For connection update procedure. XXX: can make this a pointer and
|
||||
* malloc it if we want to save space.
|
||||
*/
|
||||
struct hci_conn_update conn_param_req;
|
||||
|
||||
/* For connection update procedure */
|
||||
struct ble_ll_conn_upd_req conn_update_req;
|
||||
|
||||
/* XXX: for now, just store them all */
|
||||
struct ble_ll_conn_params conn_cp;
|
||||
|
||||
struct ble_ll_scan_sm *scansm;
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
|
||||
struct hci_ext_create_conn initial_params;
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER)
|
||||
uint8_t sync_transfer_mode;
|
||||
uint16_t sync_transfer_skip;
|
||||
uint32_t sync_transfer_sync_timeout;
|
||||
#endif
|
||||
};
|
||||
|
||||
/* Flags */
|
||||
#define CONN_F_UPDATE_SCHED(csm) ((csm)->csmflags.cfbit.conn_update_sched)
|
||||
#define CONN_F_EMPTY_PDU_TXD(csm) ((csm)->csmflags.cfbit.conn_empty_pdu_txd)
|
||||
#define CONN_F_LAST_TXD_MD(csm) ((csm)->csmflags.cfbit.last_txd_md)
|
||||
#define CONN_F_CONN_REQ_TXD(csm) ((csm)->csmflags.cfbit.conn_req_txd)
|
||||
#define CONN_F_ENCRYPTED(csm) ((csm)->csmflags.cfbit.encrypted)
|
||||
#define CONN_F_ENC_CHANGE_SENT(csm) ((csm)->csmflags.cfbit.encrypt_chg_sent)
|
||||
#define CONN_F_LE_PING_SUPP(csm) ((csm)->csmflags.cfbit.le_ping_supp)
|
||||
#define CONN_F_TERMINATE_STARTED(csm) ((csm)->csmflags.cfbit.terminate_started)
|
||||
#define CONN_F_CSA2_SUPP(csm) ((csm)->csmflags.cfbit.csa2_supp)
|
||||
#define CONN_F_HOST_PHY_UPDATE(csm) ((csm)->csmflags.cfbit.host_phy_update)
|
||||
#define CONN_F_PHY_UPDATE_SCHED(csm) ((csm)->csmflags.cfbit.phy_update_sched)
|
||||
#define CONN_F_CTRLR_PHY_UPDATE(csm) ((csm)->csmflags.cfbit.ctrlr_phy_update)
|
||||
#define CONN_F_PHY_UPDATE_EVENT(csm) ((csm)->csmflags.cfbit.phy_update_event)
|
||||
#define CONN_F_PEER_PHY_UPDATE(csm) ((csm)->csmflags.cfbit.peer_phy_update)
|
||||
#define CONN_F_AUX_CONN_REQ(csm) ((csm)->csmflags.cfbit.aux_conn_req)
|
||||
|
||||
/* Role */
|
||||
#define CONN_IS_MASTER(csm) (csm->conn_role == BLE_LL_CONN_ROLE_MASTER)
|
||||
#define CONN_IS_SLAVE(csm) (csm->conn_role == BLE_LL_CONN_ROLE_SLAVE)
|
||||
|
||||
/*
|
||||
* Given a handle, returns an active connection state machine (or NULL if the
|
||||
* handle does not exist
|
||||
*
|
||||
*/
|
||||
struct ble_ll_conn_sm *ble_ll_conn_find_active_conn(uint16_t handle);
|
||||
|
||||
/* required for unit testing */
|
||||
uint8_t ble_ll_conn_calc_dci(struct ble_ll_conn_sm *conn, uint16_t latency);
|
||||
|
||||
/* used to get anchor point for connection event specified */
|
||||
void ble_ll_conn_get_anchor(struct ble_ll_conn_sm *connsm, uint16_t conn_event,
|
||||
uint32_t *anchor, uint8_t *anchor_usecs);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* H_BLE_LL_CONN_ */
|
||||
@@ -0,0 +1,313 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef H_BLE_LL_CTRL_
|
||||
#define H_BLE_LL_CTRL_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* LL control procedures. This "enumeration" is not in the specification;
|
||||
* It is used to determine which LL control procedure is currently running
|
||||
* in a connection and which ones may be pending.
|
||||
*/
|
||||
#define BLE_LL_CTRL_PROC_CONN_UPDATE (0)
|
||||
#define BLE_LL_CTRL_PROC_CHAN_MAP_UPD (1)
|
||||
#define BLE_LL_CTRL_PROC_ENCRYPT (2)
|
||||
#define BLE_LL_CTRL_PROC_FEATURE_XCHG (3)
|
||||
#define BLE_LL_CTRL_PROC_VERSION_XCHG (4)
|
||||
#define BLE_LL_CTRL_PROC_TERMINATE (5)
|
||||
#define BLE_LL_CTRL_PROC_CONN_PARAM_REQ (6)
|
||||
#define BLE_LL_CTRL_PROC_LE_PING (7)
|
||||
#define BLE_LL_CTRL_PROC_DATA_LEN_UPD (8)
|
||||
#define BLE_LL_CTRL_PROC_PHY_UPDATE (9)
|
||||
#define BLE_LL_CTRL_PROC_NUM (10)
|
||||
#define BLE_LL_CTRL_PROC_IDLE (255)
|
||||
|
||||
/* Checks if a particular control procedure is running */
|
||||
#define IS_PENDING_CTRL_PROC(sm, proc) (sm->pending_ctrl_procs & (1 << proc))
|
||||
#define CLR_PENDING_CTRL_PROC(sm, proc) (sm->pending_ctrl_procs &= ~(1 << proc))
|
||||
|
||||
/* LL control procedure timeout */
|
||||
#define BLE_LL_CTRL_PROC_TIMEOUT_MS (40000) /* ms */
|
||||
|
||||
/*
|
||||
* LL CTRL PDU format
|
||||
* -> Opcode (1 byte)
|
||||
* -> Data (0 - 26 bytes)
|
||||
*/
|
||||
#define BLE_LL_CTRL_CONN_UPDATE_IND (0)
|
||||
#define BLE_LL_CTRL_CHANNEL_MAP_REQ (1)
|
||||
#define BLE_LL_CTRL_TERMINATE_IND (2)
|
||||
#define BLE_LL_CTRL_ENC_REQ (3)
|
||||
#define BLE_LL_CTRL_ENC_RSP (4)
|
||||
#define BLE_LL_CTRL_START_ENC_REQ (5)
|
||||
#define BLE_LL_CTRL_START_ENC_RSP (6)
|
||||
#define BLE_LL_CTRL_UNKNOWN_RSP (7)
|
||||
#define BLE_LL_CTRL_FEATURE_REQ (8)
|
||||
#define BLE_LL_CTRL_FEATURE_RSP (9)
|
||||
#define BLE_LL_CTRL_PAUSE_ENC_REQ (10)
|
||||
#define BLE_LL_CTRL_PAUSE_ENC_RSP (11)
|
||||
#define BLE_LL_CTRL_VERSION_IND (12)
|
||||
#define BLE_LL_CTRL_REJECT_IND (13)
|
||||
#define BLE_LL_CTRL_SLAVE_FEATURE_REQ (14)
|
||||
#define BLE_LL_CTRL_CONN_PARM_REQ (15)
|
||||
#define BLE_LL_CTRL_CONN_PARM_RSP (16)
|
||||
#define BLE_LL_CTRL_REJECT_IND_EXT (17)
|
||||
#define BLE_LL_CTRL_PING_REQ (18)
|
||||
#define BLE_LL_CTRL_PING_RSP (19)
|
||||
#define BLE_LL_CTRL_LENGTH_REQ (20)
|
||||
#define BLE_LL_CTRL_LENGTH_RSP (21)
|
||||
#define BLE_LL_CTRL_PHY_REQ (22)
|
||||
#define BLE_LL_CTRL_PHY_RSP (23)
|
||||
#define BLE_LL_CTRL_PHY_UPDATE_IND (24)
|
||||
#define BLE_LL_CTRL_MIN_USED_CHAN_IND (25)
|
||||
#define BLE_LL_CTRL_CTE_REQ (26)
|
||||
#define BLE_LL_CTRL_CTE_RSP (27)
|
||||
#define BLE_LL_CTRL_PERIODIC_SYNC_IND (28)
|
||||
#define BLE_LL_CTRL_CLOCK_ACCURACY_REQ (29)
|
||||
#define BLE_LL_CTRL_CLOCK_ACCURACY_RSP (30)
|
||||
|
||||
/* Maximum opcode value */
|
||||
#define BLE_LL_CTRL_OPCODES (BLE_LL_CTRL_CLOCK_ACCURACY_RSP + 1)
|
||||
|
||||
extern const uint8_t g_ble_ll_ctrl_pkt_lengths[BLE_LL_CTRL_OPCODES];
|
||||
|
||||
/* Maximum LL control PDU size */
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER)
|
||||
#define BLE_LL_CTRL_MAX_PDU_LEN (35)
|
||||
#else
|
||||
#define BLE_LL_CTRL_MAX_PDU_LEN (27)
|
||||
#endif
|
||||
|
||||
/* LL control connection update request */
|
||||
struct ble_ll_conn_upd_req
|
||||
{
|
||||
uint8_t winsize;
|
||||
uint16_t winoffset;
|
||||
uint16_t interval;
|
||||
uint16_t latency;
|
||||
uint16_t timeout;
|
||||
uint16_t instant;
|
||||
};
|
||||
#define BLE_LL_CTRL_CONN_UPD_REQ_LEN (11)
|
||||
|
||||
/* LL control channel map request */
|
||||
struct ble_ll_chan_map_req
|
||||
{
|
||||
uint8_t chmap[5];
|
||||
uint16_t instant;
|
||||
};
|
||||
#define BLE_LL_CTRL_CHAN_MAP_LEN (7)
|
||||
|
||||
/*
|
||||
* LL control terminate ind
|
||||
* -> error code (1 byte)
|
||||
*/
|
||||
#define BLE_LL_CTRL_TERMINATE_IND_LEN (1)
|
||||
|
||||
/* LL control enc req */
|
||||
struct ble_ll_enc_req
|
||||
{
|
||||
uint8_t rand[8];
|
||||
uint16_t ediv;
|
||||
uint8_t skdm[8];
|
||||
uint32_t ivm;
|
||||
};
|
||||
|
||||
#define BLE_LL_CTRL_ENC_REQ_LEN (22)
|
||||
|
||||
/* LL control enc rsp */
|
||||
struct ble_ll_enc_rsp
|
||||
{
|
||||
uint8_t skds[8];
|
||||
uint32_t ivs;
|
||||
};
|
||||
|
||||
#define BLE_LL_CTRL_ENC_RSP_LEN (12)
|
||||
|
||||
/* LL control start/pause enc request and response */
|
||||
#define BLE_LL_CTRL_START_ENC_REQ_LEN (0)
|
||||
#define BLE_LL_CTRL_START_ENC_RSP_LEN (0)
|
||||
#define BLE_LL_CTRL_PAUSE_ENC_REQ_LEN (0)
|
||||
#define BLE_LL_CTRL_PAUSE_ENC_RSP_LEN (0)
|
||||
|
||||
/*
|
||||
* LL control unknown response
|
||||
* -> 1 byte which contains the unknown or un-supported opcode.
|
||||
*/
|
||||
#define BLE_LL_CTRL_UNK_RSP_LEN (1)
|
||||
|
||||
/*
|
||||
* LL control feature req and LL control feature rsp
|
||||
* -> 8 bytes of data containing features supported by device.
|
||||
*/
|
||||
#define BLE_LL_CTRL_FEATURE_LEN (8)
|
||||
|
||||
/*
|
||||
* LL control version ind
|
||||
* -> version (1 byte):
|
||||
* Contains the version number of the bluetooth controller specification.
|
||||
* -> comp_id (2 bytes)
|
||||
* Contains the company identifier of the manufacturer of the controller.
|
||||
* -> sub_ver_num: Contains a unique value for implementation or revision of
|
||||
* the bluetooth controller.
|
||||
*/
|
||||
struct ble_ll_version_ind
|
||||
{
|
||||
uint8_t ble_ctrlr_ver;
|
||||
uint16_t company_id;
|
||||
uint16_t sub_ver_num;
|
||||
};
|
||||
|
||||
#define BLE_LL_CTRL_VERSION_IND_LEN (5)
|
||||
|
||||
/*
|
||||
* LL control reject ind
|
||||
* -> error code (1 byte): contains reason why request was rejected.
|
||||
*/
|
||||
#define BLE_LL_CTRL_REJ_IND_LEN (1)
|
||||
|
||||
/*
|
||||
* LL control slave feature req
|
||||
* -> 8 bytes of data containing features supported by device.
|
||||
*/
|
||||
#define BLE_LL_CTRL_SLAVE_FEATURE_REQ_LEN (8)
|
||||
|
||||
/* LL control connection param req and connection param rsp */
|
||||
struct ble_ll_conn_params
|
||||
{
|
||||
uint16_t interval_min;
|
||||
uint16_t interval_max;
|
||||
uint16_t latency;
|
||||
uint16_t timeout;
|
||||
uint8_t pref_periodicity;
|
||||
uint16_t ref_conn_event_cnt;
|
||||
uint16_t offset0;
|
||||
uint16_t offset1;
|
||||
uint16_t offset2;
|
||||
uint16_t offset3;
|
||||
uint16_t offset4;
|
||||
uint16_t offset5;
|
||||
};
|
||||
|
||||
#define BLE_LL_CTRL_CONN_PARAMS_LEN (23)
|
||||
|
||||
/* LL control reject ind ext */
|
||||
struct ble_ll_reject_ind_ext
|
||||
{
|
||||
uint8_t reject_opcode;
|
||||
uint8_t err_code;
|
||||
};
|
||||
|
||||
#define BLE_LL_CTRL_REJECT_IND_EXT_LEN (2)
|
||||
|
||||
/* LL control ping req and ping rsp (contain no data) */
|
||||
#define BLE_LL_CTRL_PING_LEN (0)
|
||||
|
||||
/*
|
||||
* LL control length req and length rsp
|
||||
* -> max_rx_bytes (2 bytes): defines connMaxRxOctets. Range 27 to 251
|
||||
* -> max_rx_time (2 bytes): defines connMaxRxTime. Range 328 to 2120 usecs.
|
||||
* -> max_tx_bytes (2 bytes): defines connMaxTxOctets. Range 27 to 251
|
||||
* -> max_tx_time (2 bytes): defines connMaxTxTime. Range 328 to 2120 usecs.
|
||||
*/
|
||||
struct ble_ll_len_req
|
||||
{
|
||||
uint16_t max_rx_bytes;
|
||||
uint16_t max_rx_time;
|
||||
uint16_t max_tx_bytes;
|
||||
uint16_t max_tx_time;
|
||||
};
|
||||
|
||||
#define BLE_LL_CTRL_LENGTH_REQ_LEN (8)
|
||||
|
||||
/* PHY request/response */
|
||||
#define BLE_LL_CTRL_PHY_REQ_LEN (2)
|
||||
#define BLE_LL_CTRL_PHY_RSP_LEN (2)
|
||||
#define BLE_LL_CTRL_PHY_UPD_IND_LEN (4)
|
||||
|
||||
/* Min used channels */
|
||||
#define BLE_LL_CTRL_MIN_USED_CHAN_LEN (2)
|
||||
|
||||
/* CTE REQ */
|
||||
#define BLE_LL_CTRL_CTE_REQ_LEN (1)
|
||||
|
||||
/* CTE RSP (contains no data) */
|
||||
#define BLE_LL_CTRL_CTE_RSP_LEN (0)
|
||||
|
||||
/* Periodic Sync Transfer IND */
|
||||
#define BLE_LL_CTRL_PERIODIC_SYNC_IND_LEN (34)
|
||||
|
||||
/* Clock accuracy request/response */
|
||||
#define BLE_LL_CTRL_CLOCK_ACCURACY_REQ_LEN (1)
|
||||
#define BLE_LL_CTRL_CLOCK_ACCURACY_RSP_LEN (1)
|
||||
|
||||
/* API */
|
||||
struct ble_ll_conn_sm;
|
||||
void ble_ll_ctrl_proc_start(struct ble_ll_conn_sm *connsm, int ctrl_proc);
|
||||
void ble_ll_ctrl_proc_stop(struct ble_ll_conn_sm *connsm, int ctrl_proc);
|
||||
int ble_ll_ctrl_rx_pdu(struct ble_ll_conn_sm *connsm, struct os_mbuf *om);
|
||||
void ble_ll_ctrl_chk_proc_start(struct ble_ll_conn_sm *connsm);
|
||||
void ble_ll_ctrl_terminate_start(struct ble_ll_conn_sm *connsm);
|
||||
int ble_ll_ctrl_is_terminate_ind(uint8_t hdr, uint8_t opcode);
|
||||
uint8_t ble_ll_ctrl_conn_param_reply(struct ble_ll_conn_sm *connsm,
|
||||
uint8_t *rsp,
|
||||
struct ble_ll_conn_params *req);
|
||||
int ble_ll_ctrl_reject_ind_send(struct ble_ll_conn_sm *connsm,
|
||||
uint8_t rej_opcode, uint8_t err);
|
||||
int ble_ll_ctrl_start_enc_send(struct ble_ll_conn_sm *connsm);
|
||||
int ble_ll_ctrl_enc_allowed_pdu_rx(struct os_mbuf *rxpdu);
|
||||
int ble_ll_ctrl_enc_allowed_pdu_tx(struct os_mbuf_pkthdr *pkthdr);
|
||||
int ble_ll_ctrl_tx_done(struct os_mbuf *txpdu, struct ble_ll_conn_sm *connsm);
|
||||
int ble_ll_ctrl_is_start_enc_rsp(struct os_mbuf *txpdu);
|
||||
|
||||
void ble_ll_hci_ev_datalen_chg(struct ble_ll_conn_sm *connsm);
|
||||
void ble_ll_hci_ev_rem_conn_parm_req(struct ble_ll_conn_sm *connsm,
|
||||
struct ble_ll_conn_params *cp);
|
||||
void ble_ll_hci_ev_conn_update(struct ble_ll_conn_sm *connsm, uint8_t status);
|
||||
void ble_ll_hci_ev_rd_rem_used_feat(struct ble_ll_conn_sm *connsm,
|
||||
uint8_t status);
|
||||
void ble_ll_hci_ev_rd_rem_ver(struct ble_ll_conn_sm *connsm, uint8_t status);
|
||||
void ble_ll_hci_ev_encrypt_chg(struct ble_ll_conn_sm *connsm, uint8_t status);
|
||||
int ble_ll_hci_ev_ltk_req(struct ble_ll_conn_sm *connsm);
|
||||
int ble_ll_hci_ev_hw_err(uint8_t hw_err);
|
||||
void ble_ll_hci_ev_databuf_overflow(void);
|
||||
void ble_ll_hci_ev_le_csa(struct ble_ll_conn_sm *connsm);
|
||||
void ble_ll_hci_ev_send_scan_req_recv(uint8_t adv_handle, const uint8_t *peer,
|
||||
uint8_t peer_addr_type);
|
||||
void ble_ll_hci_ev_send_scan_timeout(void);
|
||||
void ble_ll_hci_ev_send_adv_set_terminated(uint8_t status, uint8_t adv_handle,
|
||||
uint16_t conn_handle, uint8_t events);
|
||||
int ble_ll_hci_ev_phy_update(struct ble_ll_conn_sm *connsm, uint8_t status);
|
||||
void ble_ll_calc_session_key(struct ble_ll_conn_sm *connsm);
|
||||
void ble_ll_ctrl_phy_update_proc_complete(struct ble_ll_conn_sm *connsm);
|
||||
void ble_ll_ctrl_initiate_dle(struct ble_ll_conn_sm *connsm);
|
||||
void ble_ll_hci_ev_send_vendor_err(const char *file, uint32_t line);
|
||||
|
||||
uint8_t ble_ll_ctrl_phy_tx_transition_get(uint8_t phy_mask);
|
||||
uint8_t ble_ll_ctrl_phy_from_phy_mask(uint8_t phy_mask);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* H_BLE_LL_CTRL_ */
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef H_BLE_LL_HCI_
|
||||
#define H_BLE_LL_HCI_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "nimble/nimble/include/nimble/hci_common.h"
|
||||
|
||||
/* For supported commands */
|
||||
#define BLE_LL_SUPP_CMD_LEN (42)
|
||||
extern const uint8_t g_ble_ll_supp_cmds[BLE_LL_SUPP_CMD_LEN];
|
||||
|
||||
/* The largest event the controller will send. */
|
||||
#define BLE_LL_MAX_EVT_LEN MYNEWT_VAL(BLE_HCI_EVT_BUF_SIZE)
|
||||
|
||||
/*
|
||||
* This determines the number of outstanding commands allowed from the
|
||||
* host to the controller. NOTE: you cannot change this without modifying
|
||||
* other portions of the code as we currently use a global os event for
|
||||
* the command; you would need to allocate a pool of these.
|
||||
*/
|
||||
#define BLE_LL_CFG_NUM_HCI_CMD_PKTS (1)
|
||||
|
||||
typedef void (*ble_ll_hci_post_cmd_complete_cb)(void);
|
||||
|
||||
/* Initialize LL HCI */
|
||||
void ble_ll_hci_init(void);
|
||||
|
||||
/* Used to determine if the LE event is enabled/disabled */
|
||||
bool ble_ll_hci_is_le_event_enabled(unsigned int subev);
|
||||
|
||||
/* Used to determine if event is enabled/disabled */
|
||||
bool ble_ll_hci_is_event_enabled(unsigned int evcode);
|
||||
|
||||
/* Send event from controller to host */
|
||||
int ble_ll_hci_event_send(struct ble_hci_ev *hci_ev);
|
||||
|
||||
/* Sends a command complete with a no-op opcode to host */
|
||||
void ble_ll_hci_send_noop(void);
|
||||
|
||||
/* Checks the preferref phy masks from set default phy and set phy commands */
|
||||
int ble_ll_hci_chk_phy_masks(uint8_t all_phys, uint8_t tx_phys, uint8_t rx_phys,
|
||||
uint8_t *txphy, uint8_t *rxphy);
|
||||
|
||||
/* Returns true if Extended Advertising HCI commands are in use */
|
||||
bool ble_ll_hci_adv_mode_ext(void);
|
||||
|
||||
/* Get TX power compensation rounded to integer dB */
|
||||
int8_t ble_ll_get_tx_pwr_compensation(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* H_BLE_LL_HCI_ */
|
||||
@@ -0,0 +1,116 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef H_BLE_LL_RESOLV_
|
||||
#define H_BLE_LL_RESOLV_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* An entry in the resolving list.
|
||||
* The identity address is stored in little endian format.
|
||||
* The local rpa is stored in little endian format.
|
||||
* The IRKs are stored in big endian format.
|
||||
*
|
||||
* Note:
|
||||
* rl_local_irk and rl_peer_irk need to be word aligned
|
||||
*/
|
||||
struct ble_ll_resolv_entry
|
||||
{
|
||||
uint8_t rl_addr_type;
|
||||
uint8_t rl_priv_mode;
|
||||
uint8_t rl_has_local;
|
||||
uint8_t rl_has_peer;
|
||||
uint8_t rl_local_irk[16];
|
||||
uint8_t rl_peer_irk[16];
|
||||
uint8_t rl_identity_addr[BLE_DEV_ADDR_LEN];
|
||||
uint8_t rl_local_rpa[BLE_DEV_ADDR_LEN];
|
||||
uint8_t rl_peer_rpa[BLE_DEV_ADDR_LEN];
|
||||
};
|
||||
|
||||
extern struct ble_ll_resolv_entry g_ble_ll_resolv_list[];
|
||||
|
||||
/* Clear the resolving list */
|
||||
int ble_ll_resolv_list_clr(void);
|
||||
|
||||
/* Read the size of the resolving list */
|
||||
int ble_ll_resolv_list_read_size(uint8_t *rspbuf, uint8_t *rsplen);
|
||||
|
||||
/* Add a device to the resolving list */
|
||||
int ble_ll_resolv_list_add(const uint8_t *cmdbuf, uint8_t len);
|
||||
|
||||
/* Remove a device from the resolving list */
|
||||
int ble_ll_resolv_list_rmv(const uint8_t *cmdbuf, uint8_t len);
|
||||
|
||||
/* Address resolution enable command */
|
||||
int ble_ll_resolv_enable_cmd(const uint8_t *cmdbuf, uint8_t len);
|
||||
|
||||
int ble_ll_resolv_peer_addr_rd(const uint8_t *cmdbuf, uint8_t len,
|
||||
uint8_t *rspbuf, uint8_t *rsplen);
|
||||
int ble_ll_resolv_local_addr_rd(const uint8_t *cmdbuf, uint8_t len,
|
||||
uint8_t *rspbuf, uint8_t *rsplen);
|
||||
|
||||
/* Finds 'addr' in resolving list. Doesnt check if address resolution enabled */
|
||||
struct ble_ll_resolv_entry *
|
||||
ble_ll_resolv_list_find(const uint8_t *addr, uint8_t addr_type);
|
||||
|
||||
/* Returns true if address resolution is enabled */
|
||||
uint8_t ble_ll_resolv_enabled(void);
|
||||
|
||||
/* Reset private address resolution */
|
||||
void ble_ll_resolv_list_reset(void);
|
||||
|
||||
/* Generate local or peer RPA. It is up to caller to make sure required IRK
|
||||
* is present on RL
|
||||
*/
|
||||
void ble_ll_resolv_get_priv_addr(struct ble_ll_resolv_entry *rl, int local,
|
||||
uint8_t *addr);
|
||||
|
||||
void ble_ll_resolv_set_peer_rpa(int index, uint8_t *rpa);
|
||||
void ble_ll_resolv_set_local_rpa(int index, uint8_t *rpa);
|
||||
|
||||
/* Generate a resolvable private address. */
|
||||
int ble_ll_resolv_gen_rpa(uint8_t *addr, uint8_t addr_type, uint8_t *rpa,
|
||||
int local);
|
||||
|
||||
/* Set the resolvable private address timeout */
|
||||
int ble_ll_resolv_set_rpa_tmo(const uint8_t *cmdbuf, uint8_t len);
|
||||
|
||||
/* Set the privacy mode */
|
||||
int ble_ll_resolve_set_priv_mode(const uint8_t *cmdbuf, uint8_t len);
|
||||
|
||||
/* Get the RPA timeout, in seconds */
|
||||
uint32_t ble_ll_resolv_get_rpa_tmo(void);
|
||||
|
||||
/* Resolve a resolvable private address */
|
||||
int ble_ll_resolv_rpa(const uint8_t *rpa, const uint8_t *irk);
|
||||
|
||||
/* Try to resolve peer RPA and return index on RL if matched */
|
||||
int ble_ll_resolv_peer_rpa_any(const uint8_t *rpa);
|
||||
|
||||
/* Initialize resolv*/
|
||||
void ble_ll_resolv_init(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,63 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef H_BLE_LL_RFMGMT_
|
||||
#define H_BLE_LL_RFMGMT_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void ble_ll_rfmgmt_init(void);
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_RFMGMT_ENABLE_TIME) > 0
|
||||
|
||||
void ble_ll_rfmgmt_reset(void);
|
||||
|
||||
/* Notify rfmgmt that scan window has changed (only called from ble_ll_scan) */
|
||||
void ble_ll_rfmgmt_scan_changed(bool enabled, uint32_t next_window);
|
||||
|
||||
/* Notify rfmgmt that 1st scheduled item has changed (only called from ble_ll_sched) */
|
||||
void ble_ll_rfmgmt_sched_changed(struct ble_ll_sched_item *first);
|
||||
|
||||
/* Notify rfmgmt that RF is no longer needed by current event */
|
||||
void ble_ll_rfmgmt_release(void);
|
||||
|
||||
/* Enables RF immediately and returns tick at which RF will be fully enabled */
|
||||
uint32_t ble_ll_rfmgmt_enable_now(void);
|
||||
|
||||
/* Returns true only if RF is currently fully enabled (i.e. not off or enabling) */
|
||||
bool ble_ll_rfmgmt_is_enabled(void);
|
||||
|
||||
#else
|
||||
|
||||
static inline void ble_ll_rfmgmt_reset(void) { }
|
||||
static inline void ble_ll_rfmgmt_scan_changed(bool e, uint32_t n) { }
|
||||
static inline void ble_ll_rfmgmt_sched_changed(struct ble_ll_sched_item *f) { }
|
||||
static inline void ble_ll_rfmgmt_release(void) { }
|
||||
static inline uint32_t ble_ll_rfmgmt_enable_now(void) { return 0; }
|
||||
static inline bool ble_ll_rfmgmt_is_enabled(void) { return true; }
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* H_BLE_LL_RFMGMT_ */
|
||||
@@ -0,0 +1,293 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef H_BLE_LL_SCAN_
|
||||
#define H_BLE_LL_SCAN_
|
||||
|
||||
#include "ble_ll_sched.h"
|
||||
#include "nimble/porting/nimble/include/hal/hal_timer.h"
|
||||
#include "nimble/porting/nimble/include/syscfg/syscfg.h"
|
||||
#include "nimble/nimble/include/nimble/nimble_npl.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* SCAN_REQ
|
||||
* -> ScanA (6 bytes)
|
||||
* -> AdvA (6 bytes)
|
||||
*
|
||||
* ScanA is the scanners public (TxAdd=0) or random (TxAdd = 1) address
|
||||
* AdvaA is the advertisers public (RxAdd=0) or random (RxAdd=1) address.
|
||||
*
|
||||
* Sent by the LL in the Scanning state; received by the LL in the advertising
|
||||
* state. The advertising address is the intended recipient of this frame.
|
||||
*/
|
||||
#define BLE_SCAN_REQ_LEN (12)
|
||||
|
||||
/*
|
||||
* SCAN_RSP
|
||||
* -> AdvA (6 bytes)
|
||||
* -> ScanRspData (0 - 31 bytes)
|
||||
*
|
||||
* AdvaA is the advertisers public (TxAdd=0) or random (TxAdd=1) address.
|
||||
* ScanRspData may contain any data from the advertisers host.
|
||||
*
|
||||
* Sent by the LL in the advertising state; received by the LL in the
|
||||
* scanning state.
|
||||
*/
|
||||
#define BLE_SCAN_RSP_LEGACY_DATA_MAX_LEN (31)
|
||||
#define BLE_SCAN_LEGACY_MAX_PKT_LEN (37)
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
|
||||
#define BLE_SCAN_RSP_DATA_MAX_LEN MYNEWT_VAL(BLE_EXT_ADV_MAX_SIZE)
|
||||
|
||||
/* For Bluetooth 5.0 we need state machine for two PHYs*/
|
||||
#define BLE_LL_SCAN_PHY_NUMBER (2)
|
||||
#else
|
||||
#define BLE_LL_SCAN_PHY_NUMBER (1)
|
||||
#define BLE_SCAN_RSP_DATA_MAX_LEN BLE_SCAN_RSP_LEGACY_DATA_MAX_LEN
|
||||
#endif
|
||||
|
||||
#define PHY_UNCODED (0)
|
||||
#define PHY_CODED (1)
|
||||
|
||||
#define BLE_LL_EXT_ADV_MODE_NON_CONN (0x00)
|
||||
#define BLE_LL_EXT_ADV_MODE_CONN (0x01)
|
||||
#define BLE_LL_EXT_ADV_MODE_SCAN (0x02)
|
||||
|
||||
/* All values are stored as ticks */
|
||||
struct ble_ll_scan_timing {
|
||||
uint32_t interval;
|
||||
uint32_t window;
|
||||
uint32_t start_time;
|
||||
};
|
||||
|
||||
struct ble_ll_scan_params
|
||||
{
|
||||
uint8_t phy;
|
||||
uint8_t own_addr_type;
|
||||
uint8_t scan_filt_policy;
|
||||
uint8_t configured;
|
||||
uint8_t scan_type;
|
||||
uint8_t scan_chan;
|
||||
struct ble_ll_scan_timing timing;
|
||||
};
|
||||
|
||||
#define BLE_LL_AUX_HAS_ADVA 0x01
|
||||
#define BLE_LL_AUX_HAS_TARGETA 0x02
|
||||
#define BLE_LL_AUX_HAS_ADI 0x04
|
||||
#define BLE_LL_AUX_IS_MATCHED 0x08
|
||||
#define BLE_LL_AUX_IS_TARGETA_RESOLVED 0x10
|
||||
|
||||
#define BLE_LL_AUX_FLAG_HCI_SENT_ANY 0x02
|
||||
#define BLE_LL_AUX_FLAG_HCI_SENT_COMPLETED 0x04
|
||||
#define BLE_LL_AUX_FLAG_HCI_SENT_TRUNCATED 0x08
|
||||
#define BLE_LL_AUX_FLAG_SCAN_COMPLETE 0x10
|
||||
#define BLE_LL_AUX_FLAG_SCAN_ERROR 0x20
|
||||
#define BLE_LL_AUX_FLAG_AUX_ADV_RECEIVED 0x40
|
||||
#define BLE_LL_AUX_FLAG_AUX_CHAIN_RECEIVED 0x80
|
||||
|
||||
struct ble_ll_aux_data {
|
||||
uint8_t flags;
|
||||
|
||||
/*
|
||||
* Since aux_data can be accessed from ISR and LL, we have separate copies
|
||||
* of flags to make sure that ISR does not modify flags while LL uses them.
|
||||
* ISR updates 'flags_isr' and LL adds these to 'flags_ll' which it then
|
||||
* uses for further processing allowing to update 'flags_isr' if another
|
||||
* scan for given 'aux_data' is scheduled. Note that flags must not be unset
|
||||
* while aux_data is valid.
|
||||
*/
|
||||
uint8_t flags_isr;
|
||||
uint8_t flags_ll;
|
||||
|
||||
uint8_t ref_cnt;
|
||||
uint8_t chan;
|
||||
uint8_t aux_phy;
|
||||
uint8_t aux_primary_phy;
|
||||
uint8_t mode;
|
||||
uint8_t scanning;
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
|
||||
int8_t rpa_index;
|
||||
#endif
|
||||
uint16_t adi;
|
||||
uint32_t offset;
|
||||
uint8_t offset_units;
|
||||
uint8_t adva[6];
|
||||
uint8_t adva_type;
|
||||
uint8_t targeta[6];
|
||||
uint8_t targeta_type;
|
||||
uint16_t evt_type;
|
||||
struct ble_ll_sched_item sch;
|
||||
struct ble_hci_ev *evt;
|
||||
struct ble_npl_event ev;
|
||||
};
|
||||
|
||||
struct ble_ll_scan_pdu_data {
|
||||
uint8_t hdr_byte;
|
||||
/* ScanA for SCAN_REQ and InitA for CONNECT_IND */
|
||||
union {
|
||||
uint8_t scana[BLE_DEV_ADDR_LEN];
|
||||
uint8_t inita[BLE_DEV_ADDR_LEN];
|
||||
};
|
||||
uint8_t adva[BLE_DEV_ADDR_LEN];
|
||||
};
|
||||
|
||||
struct ble_ll_scan_sm
|
||||
{
|
||||
uint8_t scan_enabled;
|
||||
uint8_t own_addr_type;
|
||||
uint8_t scan_filt_dups;
|
||||
uint8_t scan_rsp_pending;
|
||||
uint8_t scan_rsp_cons_fails;
|
||||
uint8_t scan_rsp_cons_ok;
|
||||
uint8_t scan_peer_rpa[BLE_DEV_ADDR_LEN];
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
|
||||
ble_npl_time_t scan_nrpa_timer;
|
||||
uint8_t scan_nrpa[BLE_DEV_ADDR_LEN];
|
||||
#endif
|
||||
struct ble_ll_scan_pdu_data pdu_data;
|
||||
|
||||
/* XXX: Shall we count backoff per phy? */
|
||||
uint16_t upper_limit;
|
||||
uint16_t backoff_count;
|
||||
uint32_t scan_win_start_time;
|
||||
struct ble_npl_event scan_sched_ev;
|
||||
struct hal_timer scan_timer;
|
||||
struct ble_npl_event scan_interrupted_ev;
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
|
||||
struct hal_timer duration_timer;
|
||||
struct hal_timer period_timer;
|
||||
uint32_t duration_ticks;
|
||||
uint32_t period_ticks;
|
||||
uint8_t ext_scanning;
|
||||
#endif
|
||||
|
||||
uint8_t restart_timer_needed;
|
||||
struct ble_ll_aux_data *cur_aux_data;
|
||||
|
||||
struct ble_ll_scan_params *scanp;
|
||||
struct ble_ll_scan_params *scanp_next;
|
||||
struct ble_ll_scan_params scanp_phys[BLE_LL_SCAN_PHY_NUMBER];
|
||||
};
|
||||
|
||||
/* Scan types */
|
||||
#define BLE_SCAN_TYPE_PASSIVE (BLE_HCI_SCAN_TYPE_PASSIVE)
|
||||
#define BLE_SCAN_TYPE_ACTIVE (BLE_HCI_SCAN_TYPE_ACTIVE)
|
||||
#define BLE_SCAN_TYPE_INITIATE (2)
|
||||
|
||||
/*---- HCI ----*/
|
||||
/* Set scanning parameters */
|
||||
int ble_ll_scan_set_scan_params(const uint8_t *cmdbuf, uint8_t len);
|
||||
|
||||
/* Turn scanning on/off */
|
||||
int ble_ll_hci_scan_set_enable(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_hci_ext_scan_set_enable(const uint8_t *cmdbuf, uint8_t len);
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
|
||||
int ble_ll_set_ext_scan_params(const uint8_t *cmdbuf, uint8_t len);
|
||||
#endif
|
||||
|
||||
/*--- Controller Internal API ---*/
|
||||
/* Initialize the scanner */
|
||||
void ble_ll_scan_init(void);
|
||||
|
||||
/* Reset the scanner */
|
||||
void ble_ll_scan_reset(void);
|
||||
|
||||
/* Called when Link Layer starts to receive a PDU and is in scanning state */
|
||||
int ble_ll_scan_rx_isr_start(uint8_t pdu_type, uint16_t *rxflags);
|
||||
|
||||
/* Called when Link Layer has finished receiving a PDU while scanning */
|
||||
int ble_ll_scan_rx_isr_end(struct os_mbuf *rxpdu, uint8_t crcok);
|
||||
|
||||
/* Process a scan response PDU */
|
||||
void ble_ll_scan_rx_pkt_in(uint8_t pdu_type, struct os_mbuf *om,
|
||||
struct ble_mbuf_hdr *hdr);
|
||||
|
||||
/* Boolean function denoting whether or not the whitelist can be changed */
|
||||
int ble_ll_scan_can_chg_whitelist(void);
|
||||
|
||||
/* Boolean function returning true if scanning enabled */
|
||||
int ble_ll_scan_enabled(void);
|
||||
|
||||
/* Boolean function returns true if whitelist is enabled for scanning */
|
||||
int ble_ll_scan_whitelist_enabled(void);
|
||||
|
||||
/* Initialize the scanner when we start initiating */
|
||||
struct hci_create_conn;
|
||||
int ble_ll_scan_initiator_start(struct hci_create_conn *hcc,
|
||||
struct ble_ll_scan_sm **sm);
|
||||
|
||||
/* Returns storage for PDU data (for SCAN_REQ or CONNECT_IND) */
|
||||
struct ble_ll_scan_pdu_data *ble_ll_scan_get_pdu_data(void);
|
||||
|
||||
/* Called to set the resolvable private address of the last connected peer */
|
||||
void ble_ll_scan_set_peer_rpa(uint8_t *rpa);
|
||||
|
||||
/* Returns peer RPA of last connection made */
|
||||
uint8_t *ble_ll_scan_get_peer_rpa(void);
|
||||
|
||||
/* Returns the local RPA used by the scanner/initiator */
|
||||
uint8_t *ble_ll_scan_get_local_rpa(void);
|
||||
|
||||
/* Stop the scanning state machine */
|
||||
void ble_ll_scan_sm_stop(int chk_disable);
|
||||
|
||||
/* Resume scanning */
|
||||
void ble_ll_scan_chk_resume(void);
|
||||
|
||||
/* Called when wait for response timer expires in scanning mode */
|
||||
void ble_ll_scan_wfr_timer_exp(void);
|
||||
|
||||
/* Called when scan could be interrupted */
|
||||
void ble_ll_scan_interrupted(struct ble_ll_scan_sm *scansm);
|
||||
|
||||
int ble_ll_scan_adv_decode_addr(uint8_t pdu_type, uint8_t *rxbuf,
|
||||
struct ble_mbuf_hdr *ble_hdr,
|
||||
uint8_t **addr, uint8_t *addr_type,
|
||||
uint8_t **inita, uint8_t *init_addr_type,
|
||||
int *ext_mode);
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
|
||||
int ble_ll_scan_update_aux_data(struct ble_mbuf_hdr *ble_hdr, uint8_t *rxbuf,
|
||||
bool *adva_present);
|
||||
|
||||
/* Initialize the extended scanner when we start initiating */
|
||||
struct hci_ext_create_conn;
|
||||
int ble_ll_scan_ext_initiator_start(struct hci_ext_create_conn *hcc,
|
||||
struct ble_ll_scan_sm **sm);
|
||||
|
||||
/* Called to parse extended advertising*/
|
||||
struct ble_ll_aux_data *ble_ll_scan_aux_data_ref(struct ble_ll_aux_data *aux_scan);
|
||||
void ble_ll_scan_aux_data_unref(struct ble_ll_aux_data *aux_scan);
|
||||
void ble_ll_scan_end_adv_evt(struct ble_ll_aux_data *aux_data);
|
||||
#endif
|
||||
|
||||
/* Called to halt currently running scan */
|
||||
void ble_ll_scan_halt(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* H_BLE_LL_SCAN_ */
|
||||
@@ -0,0 +1,216 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef H_BLE_LL_SCHED_
|
||||
#define H_BLE_LL_SCHED_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Time per BLE scheduler slot */
|
||||
#define BLE_LL_SCHED_USECS_PER_SLOT (1250)
|
||||
#define BLE_LL_SCHED_32KHZ_TICKS_PER_SLOT (41) /* 1 tick = 30.517 usecs */
|
||||
|
||||
/*
|
||||
* Worst case time needed for scheduled advertising item. This is the longest
|
||||
* possible time to receive a scan request and send a scan response (with the
|
||||
* appropriate IFS time between them). This number is calculated using the
|
||||
* following formula: IFS + SCAN_REQ + IFS + SCAN_RSP = 150 + 176 + 150 + 376.
|
||||
* Note: worst case time to tx adv, rx scan req and send scan rsp is 1228 usecs.
|
||||
* This assumes maximum sized advertising PDU and scan response PDU.
|
||||
*
|
||||
* For connectable advertising events no scan request is allowed. In this case
|
||||
* we just need to receive a connect request PDU: IFS + CONNECT_REQ = 150 + 352.
|
||||
* Note: worst-case is 376 + 150 + 352 = 878 usecs
|
||||
*
|
||||
* NOTE: The advertising PDU transmit time is NOT included here since we know
|
||||
* how long that will take (worst-case is 376 usecs).
|
||||
*/
|
||||
#define BLE_LL_SCHED_ADV_MAX_USECS (852)
|
||||
#define BLE_LL_SCHED_DIRECT_ADV_MAX_USECS (502)
|
||||
#define BLE_LL_SCHED_MAX_ADV_PDU_USECS (376)
|
||||
|
||||
/*
|
||||
* This is the offset from the start of the scheduled item until the actual
|
||||
* tx/rx should occur, in ticks.
|
||||
*/
|
||||
extern uint8_t g_ble_ll_sched_offset_ticks;
|
||||
|
||||
/*
|
||||
* This is the number of slots needed to transmit and receive a maximum
|
||||
* size PDU, including an IFS time before each. The actual time is
|
||||
* 2120 usecs for tx/rx and 150 for IFS = 4540 usecs.
|
||||
*/
|
||||
#define BLE_LL_SCHED_MAX_TXRX_SLOT (4 * BLE_LL_SCHED_USECS_PER_SLOT)
|
||||
|
||||
/* BLE scheduler errors */
|
||||
#define BLE_LL_SCHED_ERR_OVERLAP (1)
|
||||
|
||||
/* Types of scheduler events */
|
||||
#define BLE_LL_SCHED_TYPE_ADV (1)
|
||||
#define BLE_LL_SCHED_TYPE_SCAN (2)
|
||||
#define BLE_LL_SCHED_TYPE_CONN (3)
|
||||
#define BLE_LL_SCHED_TYPE_AUX_SCAN (4)
|
||||
#define BLE_LL_SCHED_TYPE_DTM (5)
|
||||
#define BLE_LL_SCHED_TYPE_PERIODIC (6)
|
||||
#define BLE_LL_SCHED_TYPE_SYNC (7)
|
||||
|
||||
/* Return values for schedule callback. */
|
||||
#define BLE_LL_SCHED_STATE_RUNNING (0)
|
||||
#define BLE_LL_SCHED_STATE_DONE (1)
|
||||
|
||||
/* Callback function */
|
||||
struct ble_ll_sched_item;
|
||||
typedef int (*sched_cb_func)(struct ble_ll_sched_item *sch);
|
||||
typedef void (*sched_remove_cb_func)(struct ble_ll_sched_item *sch);
|
||||
/*
|
||||
* Strict connection scheduling (for the master) is different than how
|
||||
* connections are normally scheduled. With strict connection scheduling we
|
||||
* introduce the concept of a "period". A period is a collection of slots. Each
|
||||
* slot is 1.25 msecs in length. The number of slots in a period is determined
|
||||
* by the syscfg value BLE_LL_CONN_INIT_SLOTS. A collection of periods is called
|
||||
* an epoch. The length of an epoch is determined by the number of connections
|
||||
* (BLE_MAX_CONNECTIONS plus BLE_LL_ADD_STRICT_SCHED_PERIODS). Connections
|
||||
* will be scheduled at period boundaries. Any scanning/initiating/advertising
|
||||
* will be done in unused periods, if possible.
|
||||
*/
|
||||
#if MYNEWT_VAL(BLE_LL_STRICT_CONN_SCHEDULING)
|
||||
#define BLE_LL_SCHED_PERIODS (MYNEWT_VAL(BLE_MAX_CONNECTIONS) + \
|
||||
MYNEWT_VAL(BLE_LL_ADD_STRICT_SCHED_PERIODS))
|
||||
|
||||
struct ble_ll_sched_obj
|
||||
{
|
||||
uint8_t sch_num_occ_periods;
|
||||
uint32_t sch_occ_period_mask;
|
||||
uint32_t sch_ticks_per_period;
|
||||
uint32_t sch_ticks_per_epoch;
|
||||
uint32_t sch_epoch_start;
|
||||
};
|
||||
|
||||
extern struct ble_ll_sched_obj g_ble_ll_sched_data;
|
||||
|
||||
/*
|
||||
* XXX: TODO:
|
||||
* -> How do we know epoch start is up to date? Not wrapped?
|
||||
* -> for now, only do this with no more than 32 connections.
|
||||
* -> Do not let initiating occur if no empty sched slots
|
||||
*/
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Schedule item
|
||||
* sched_type: This is the type of the schedule item.
|
||||
* enqueued: Flag denoting if item is on the scheduler list. 0: no, 1:yes
|
||||
* remainder: # of usecs from offset till tx/rx should occur
|
||||
* txrx_offset: Number of ticks from start time until tx/rx should occur.
|
||||
*
|
||||
*/
|
||||
struct ble_ll_sched_item
|
||||
{
|
||||
uint8_t sched_type;
|
||||
uint8_t enqueued;
|
||||
uint8_t remainder;
|
||||
uint32_t start_time;
|
||||
uint32_t end_time;
|
||||
void *cb_arg;
|
||||
sched_cb_func sched_cb;
|
||||
TAILQ_ENTRY(ble_ll_sched_item) link;
|
||||
};
|
||||
|
||||
/* Initialize the scheduler */
|
||||
int ble_ll_sched_init(void);
|
||||
|
||||
/* Remove item(s) from schedule */
|
||||
int ble_ll_sched_rmv_elem(struct ble_ll_sched_item *sch);
|
||||
|
||||
void ble_ll_sched_rmv_elem_type(uint8_t type, sched_remove_cb_func remove_cb);
|
||||
|
||||
/* Schedule a new master connection */
|
||||
struct ble_ll_conn_sm;
|
||||
int ble_ll_sched_master_new(struct ble_ll_conn_sm *connsm,
|
||||
struct ble_mbuf_hdr *ble_hdr, uint8_t pyld_len);
|
||||
|
||||
/* Schedule a new slave connection */
|
||||
int ble_ll_sched_slave_new(struct ble_ll_conn_sm *connsm);
|
||||
|
||||
struct ble_ll_adv_sm;
|
||||
typedef void ble_ll_sched_adv_new_cb(struct ble_ll_adv_sm *advsm,
|
||||
uint32_t sch_start, void *arg);
|
||||
|
||||
/* Schedule a new advertising event */
|
||||
int ble_ll_sched_adv_new(struct ble_ll_sched_item *sch,
|
||||
ble_ll_sched_adv_new_cb cb, void *arg);
|
||||
|
||||
/* Schedule periodic advertising event */
|
||||
int ble_ll_sched_periodic_adv(struct ble_ll_sched_item *sch, uint32_t *start,
|
||||
bool after_overlap);
|
||||
|
||||
int ble_ll_sched_sync_reschedule(struct ble_ll_sched_item *sch,
|
||||
uint32_t anchor_point,
|
||||
uint8_t anchor_point_usecs,
|
||||
uint32_t window_widening, int8_t phy_mode);
|
||||
int ble_ll_sched_sync(struct ble_ll_sched_item *sch,
|
||||
uint32_t beg_cputime, uint32_t rem_usecs, uint32_t offset,
|
||||
int8_t phy_mode);
|
||||
|
||||
/* Reschedule an advertising event */
|
||||
int ble_ll_sched_adv_reschedule(struct ble_ll_sched_item *sch, uint32_t *start,
|
||||
uint32_t max_delay_ticks);
|
||||
|
||||
/* Reschedule and advertising pdu */
|
||||
int ble_ll_sched_adv_resched_pdu(struct ble_ll_sched_item *sch);
|
||||
|
||||
/* Reschedule a connection that had previously been scheduled or that is over */
|
||||
int ble_ll_sched_conn_reschedule(struct ble_ll_conn_sm * connsm);
|
||||
|
||||
/**
|
||||
* Called to determine when the next scheduled event will occur.
|
||||
*
|
||||
* If there are not scheduled events this function returns 0; otherwise it
|
||||
* returns 1 and *next_event_time is set to the start time of the next event.
|
||||
*
|
||||
* @param next_event_time cputime at which next scheduled event will occur
|
||||
*
|
||||
* @return int 0: No events are scheduled 1: there is an upcoming event
|
||||
*/
|
||||
int ble_ll_sched_next_time(uint32_t *next_event_time);
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
|
||||
struct ble_ll_scan_sm;
|
||||
struct ble_ll_aux_data;
|
||||
int ble_ll_sched_aux_scan(struct ble_mbuf_hdr *ble_hdr,
|
||||
struct ble_ll_scan_sm *scansm,
|
||||
struct ble_ll_aux_data *aux_scan);
|
||||
|
||||
int ble_ll_sched_scan_req_over_aux_ptr(uint32_t chan, uint8_t phy_mode);
|
||||
#endif
|
||||
|
||||
/* Stop the scheduler */
|
||||
void ble_ll_sched_stop(void);
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_DTM)
|
||||
int ble_ll_sched_dtm(struct ble_ll_sched_item *sch);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* H_LL_SCHED_ */
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef H_BLE_LL_SYNC_
|
||||
#define H_BLE_LL_SYNC_
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#include "nimble/nimble/include/nimble/ble.h"
|
||||
#include "ble_ll_hci.h"
|
||||
#include "ble_ll_conn.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct ble_ll_sync_sm;
|
||||
|
||||
int ble_ll_sync_create(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_sync_cancel(ble_ll_hci_post_cmd_complete_cb *post_cmd_cb);
|
||||
int ble_ll_sync_terminate(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_sync_list_add(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_sync_list_remove(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_sync_list_clear(void);
|
||||
int ble_ll_sync_list_size(uint8_t *rspbuf, uint8_t *rsplen);
|
||||
int ble_ll_sync_receive_enable(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_sync_transfer(const uint8_t *cmdbuf, uint8_t len,
|
||||
uint8_t *rspbuf, uint8_t *rsplen);
|
||||
|
||||
void ble_ll_sync_periodic_ind(struct ble_ll_conn_sm *connsm,
|
||||
const uint8_t *sync_ind, bool reports_disabled,
|
||||
uint16_t max_skip, uint32_t sync_timeout);
|
||||
void ble_ll_sync_transfer_disconnected(struct ble_ll_conn_sm *connsm);
|
||||
|
||||
void ble_ll_sync_info_event(const uint8_t *addr, uint8_t addr_type,
|
||||
int rpa_index, uint8_t sid,
|
||||
struct ble_mbuf_hdr *rxhdr,
|
||||
const uint8_t *syncinfo);
|
||||
|
||||
int ble_ll_sync_rx_isr_start(uint8_t pdu_type, struct ble_mbuf_hdr *rxhdr);
|
||||
int ble_ll_sync_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr);
|
||||
void ble_ll_sync_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr);
|
||||
void ble_ll_sync_wfr_timer_exp(void);
|
||||
void ble_ll_sync_halt(void);
|
||||
void ble_ll_sync_rmvd_from_sched(struct ble_ll_sync_sm *sm);
|
||||
|
||||
uint32_t ble_ll_sync_get_event_end_time(void);
|
||||
|
||||
bool ble_ll_sync_enabled(void);
|
||||
|
||||
void ble_ll_sync_reset(void);
|
||||
void ble_ll_sync_init(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* H_BLE_LL_SYNC_ */
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef H_LL_TEST_
|
||||
#define H_LL_TEST_
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int ble_ll_csa2_test_all(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef H_BLE_LL_TRACE_
|
||||
#define H_BLE_LL_TRACE_
|
||||
|
||||
#include "nimble/porting/nimble/include/os/os_trace_api.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define BLE_LL_TRACE_ID_SCHED 0
|
||||
#define BLE_LL_TRACE_ID_RX_START 1
|
||||
#define BLE_LL_TRACE_ID_RX_END 2
|
||||
#define BLE_LL_TRACE_ID_WFR_EXP 3
|
||||
#define BLE_LL_TRACE_ID_CTRL_RX 4
|
||||
#define BLE_LL_TRACE_ID_CONN_EV_START 5
|
||||
#define BLE_LL_TRACE_ID_CONN_EV_END 6
|
||||
#define BLE_LL_TRACE_ID_CONN_END 7
|
||||
#define BLE_LL_TRACE_ID_CONN_TX 8
|
||||
#define BLE_LL_TRACE_ID_CONN_RX 9
|
||||
#define BLE_LL_TRACE_ID_ADV_TXDONE 10
|
||||
#define BLE_LL_TRACE_ID_ADV_HALT 11
|
||||
#define BLE_LL_TRACE_ID_AUX_REF 12
|
||||
#define BLE_LL_TRACE_ID_AUX_UNREF 13
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_SYSVIEW)
|
||||
|
||||
extern uint32_t ble_ll_trace_off;
|
||||
|
||||
void ble_ll_trace_init(void);
|
||||
|
||||
static inline void
|
||||
ble_ll_trace_u32(unsigned id, uint32_t p1)
|
||||
{
|
||||
os_trace_api_u32(ble_ll_trace_off + id, p1);
|
||||
}
|
||||
|
||||
static inline void
|
||||
ble_ll_trace_u32x2(unsigned id, uint32_t p1, uint32_t p2)
|
||||
{
|
||||
os_trace_api_u32x2(ble_ll_trace_off + id, p1, p2);
|
||||
}
|
||||
|
||||
static inline void
|
||||
ble_ll_trace_u32x3(unsigned id, uint32_t p1, uint32_t p2, uint32_t p3)
|
||||
{
|
||||
os_trace_api_u32x3(ble_ll_trace_off + id, p1, p2, p3);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static inline void
|
||||
ble_ll_trace_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void
|
||||
ble_ll_trace_u32(unsigned id, uint32_t p1)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void
|
||||
ble_ll_trace_u32x2(unsigned id, uint32_t p1, uint32_t p2)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void
|
||||
ble_ll_trace_u32x3(unsigned id, uint32_t p1, uint32_t p2, uint32_t p3)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* H_BLE_LL_TRACE_ */
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
uint32_t ble_ll_utils_calc_access_addr(void);
|
||||
uint8_t ble_ll_utils_remapped_channel(uint8_t remap_index, const uint8_t *chanmap);
|
||||
uint8_t ble_ll_utils_calc_dci_csa2(uint16_t event_cntr, uint16_t channel_id,
|
||||
uint8_t num_used_chans, const uint8_t *chanmap);
|
||||
uint8_t ble_ll_utils_calc_num_used_chans(const uint8_t *chanmap);
|
||||
uint32_t ble_ll_utils_calc_window_widening(uint32_t anchor_point,
|
||||
uint32_t last_anchor_point,
|
||||
uint8_t master_sca);
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef H_BLE_LL_WHITELIST_
|
||||
#define H_BLE_LL_WHITELIST_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Clear the whitelist */
|
||||
int ble_ll_whitelist_clear(void);
|
||||
|
||||
/* Read the size of the whitelist */
|
||||
int ble_ll_whitelist_read_size(uint8_t *rspbuf, uint8_t *rsplen);
|
||||
|
||||
/* Add a device to the whitelist */
|
||||
int ble_ll_whitelist_add(const uint8_t *cmdbuf, uint8_t len);
|
||||
|
||||
/* Remove a device fromthe whitelist */
|
||||
int ble_ll_whitelist_rmv(const uint8_t *cmdbuf, uint8_t len);
|
||||
|
||||
/* Enable whitelisting */
|
||||
void ble_ll_whitelist_enable(void);
|
||||
|
||||
/* Disable whitelisting */
|
||||
void ble_ll_whitelist_disable(void);
|
||||
|
||||
/* Boolean function returning true if address matches a whitelist entry */
|
||||
int ble_ll_whitelist_match(uint8_t *addr, uint8_t addr_type, int is_ident);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* H_BLE_LL_WHITELIST_ */
|
||||
@@ -0,0 +1,242 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef H_BLE_PHY_
|
||||
#define H_BLE_PHY_
|
||||
|
||||
#include "nimble/nimble/include/nimble/hci_common.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Forward declarations */
|
||||
struct os_mbuf;
|
||||
|
||||
/* Channel/Frequency defintions */
|
||||
#define BLE_PHY_NUM_CHANS (40)
|
||||
#define BLE_PHY_NUM_DATA_CHANS (37)
|
||||
#define BLE_PHY_CHAN0_FREQ_MHZ (2402)
|
||||
#define BLE_PHY_DATA_CHAN0_FREQ_MHZ (2404)
|
||||
#define BLE_PHY_CHAN_SPACING_MHZ (2)
|
||||
#define BLE_PHY_NUM_ADV_CHANS (3)
|
||||
#define BLE_PHY_ADV_CHAN_START (37)
|
||||
|
||||
/* Power */
|
||||
#define BLE_PHY_MAX_PWR_DBM (10)
|
||||
|
||||
/* Deviation */
|
||||
#define BLE_PHY_DEV_KHZ (185)
|
||||
#define BLE_PHY_BINARY_ZERO (-BLE_PHY_DEV)
|
||||
#define BLE_PHY_BINARY_ONE (BLE_PHY_DEV)
|
||||
|
||||
/* Max. clock drift */
|
||||
#define BLE_PHY_MAX_DRIFT_PPM (50)
|
||||
|
||||
/* Data rate */
|
||||
#define BLE_PHY_BIT_RATE_BPS (1000000)
|
||||
|
||||
/* Macros */
|
||||
#define BLE_IS_ADV_CHAN(chan) (chan >= BLE_PHY_ADV_CHAN_START)
|
||||
#define BLE_IS_DATA_CHAN(chan) (chan < BLE_PHY_ADV_CHAN_START)
|
||||
|
||||
/* PHY states */
|
||||
#define BLE_PHY_STATE_IDLE (0)
|
||||
#define BLE_PHY_STATE_RX (1)
|
||||
#define BLE_PHY_STATE_TX (2)
|
||||
|
||||
/* BLE PHY transitions */
|
||||
#define BLE_PHY_TRANSITION_NONE (0)
|
||||
#define BLE_PHY_TRANSITION_RX_TX (1)
|
||||
#define BLE_PHY_TRANSITION_TX_RX (2)
|
||||
|
||||
/* PHY error codes */
|
||||
#define BLE_PHY_ERR_RADIO_STATE (1)
|
||||
#define BLE_PHY_ERR_INIT (2)
|
||||
#define BLE_PHY_ERR_INV_PARAM (3)
|
||||
#define BLE_PHY_ERR_NO_BUFS (4)
|
||||
#define BLE_PHY_ERR_TX_LATE (5)
|
||||
#define BLE_PHY_ERR_RX_LATE (6)
|
||||
|
||||
/* Maximun PDU length. Includes LL header of 2 bytes and 255 bytes payload. */
|
||||
#define BLE_PHY_MAX_PDU_LEN (257)
|
||||
|
||||
/* Wait for response timer */
|
||||
typedef void (*ble_phy_tx_end_func)(void *arg);
|
||||
|
||||
/* Initialize the PHY */
|
||||
int ble_phy_init(void);
|
||||
|
||||
/* Reset the PHY */
|
||||
int ble_phy_reset(void);
|
||||
|
||||
/* Set the PHY channel */
|
||||
int ble_phy_setchan(uint8_t chan, uint32_t access_addr, uint32_t crcinit);
|
||||
|
||||
/* Set transmit start time */
|
||||
int ble_phy_tx_set_start_time(uint32_t cputime, uint8_t rem_usecs);
|
||||
|
||||
/* Set receive start time */
|
||||
int ble_phy_rx_set_start_time(uint32_t cputime, uint8_t rem_usecs);
|
||||
|
||||
/* Set the transmit end callback and argument */
|
||||
void ble_phy_set_txend_cb(ble_phy_tx_end_func txend_cb, void *arg);
|
||||
|
||||
typedef uint8_t (*ble_phy_tx_pducb_t)(uint8_t *dptr, void *pducb_arg,
|
||||
uint8_t *hdr_byte);
|
||||
|
||||
/* Place the PHY into transmit mode */
|
||||
int ble_phy_tx(ble_phy_tx_pducb_t pducb, void *pducb_arg, uint8_t end_trans);
|
||||
|
||||
/* Place the PHY into receive mode */
|
||||
int ble_phy_rx(void);
|
||||
|
||||
/* Copies the received PHY buffer into the allocated pdu */
|
||||
void ble_phy_rxpdu_copy(uint8_t *dptr, struct os_mbuf *rxpdu);
|
||||
|
||||
/* Set the transmit power */
|
||||
int ble_phy_txpwr_set(int dbm);
|
||||
|
||||
/* Get highest allowed power from range */
|
||||
int ble_phy_txpower_round(int dbm);
|
||||
|
||||
/* Get the transmit power */
|
||||
int ble_phy_txpwr_get(void);
|
||||
|
||||
/* Set RX path power compensation value rounded to integer dB */
|
||||
void ble_phy_set_rx_pwr_compensation(int8_t compensation);
|
||||
|
||||
/* Disable the PHY */
|
||||
void ble_phy_disable(void);
|
||||
|
||||
#define BLE_PHY_WFR_ENABLE_RX (0)
|
||||
#define BLE_PHY_WFR_ENABLE_TXRX (1)
|
||||
|
||||
void ble_phy_wfr_enable(int txrx, uint8_t tx_phy_mode, uint32_t wfr_usecs);
|
||||
|
||||
/* Starts rf clock */
|
||||
void ble_phy_rfclk_enable(void);
|
||||
|
||||
/* Stops rf clock */
|
||||
void ble_phy_rfclk_disable(void);
|
||||
|
||||
/*
|
||||
* Used to restart reception on same channel after wfr timer expiration or
|
||||
* frame received.
|
||||
*/
|
||||
void ble_phy_restart_rx(void);
|
||||
|
||||
/* Gets the current state of the PHY */
|
||||
int ble_phy_state_get(void);
|
||||
|
||||
/* Gets current state of transceiver */
|
||||
uint8_t ble_phy_xcvr_state_get(void);
|
||||
|
||||
/* Returns 'true' if a reception has started */
|
||||
int ble_phy_rx_started(void);
|
||||
|
||||
/*
|
||||
* Returns the maximum supported tx/rx PDU payload size, in bytes, for data
|
||||
* channel PDUs (this does not apply to advertising channel PDUs). Note
|
||||
* that the data channel PDU is composed of a 2-byte header, the payload, and
|
||||
* an optional MIC. The maximum payload is 251 bytes.
|
||||
*/
|
||||
uint8_t ble_phy_max_data_pdu_pyld(void);
|
||||
|
||||
/* Gets the current access address */
|
||||
uint32_t ble_phy_access_addr_get(void);
|
||||
|
||||
/* Enable encryption */
|
||||
void ble_phy_encrypt_enable(uint64_t pkt_counter, uint8_t *iv, uint8_t *key,
|
||||
uint8_t is_master);
|
||||
|
||||
/* Disable encryption */
|
||||
void ble_phy_encrypt_disable(void);
|
||||
|
||||
/* Set the packet counters and dir used by LE encyption */
|
||||
void ble_phy_encrypt_set_pkt_cntr(uint64_t pkt_counter, int dir);
|
||||
|
||||
/* Enable phy resolving list */
|
||||
void ble_phy_resolv_list_enable(void);
|
||||
|
||||
/* Disable phy resolving list */
|
||||
void ble_phy_resolv_list_disable(void);
|
||||
|
||||
/*
|
||||
* PHY mode values for 1M, 2M and Coded S=8 are the same as corresponding values
|
||||
* of PHY. This makes conversion between 'phy' and 'phy_mode' easier and it also
|
||||
* means that default coding for Coded will be S=8, unless explicitly translated
|
||||
* to S=2.
|
||||
*/
|
||||
#define BLE_PHY_MODE_CODED_500KBPS (0)
|
||||
#define BLE_PHY_MODE_1M (1)
|
||||
#define BLE_PHY_MODE_2M (2)
|
||||
#define BLE_PHY_MODE_CODED_125KBPS (3)
|
||||
|
||||
/* The number of different modes */
|
||||
#define BLE_PHY_NUM_MODE (4)
|
||||
|
||||
/* PHY numbers (compatible with HCI) */
|
||||
#define BLE_PHY_1M (BLE_HCI_LE_PHY_1M)
|
||||
#define BLE_PHY_2M (BLE_HCI_LE_PHY_2M)
|
||||
#define BLE_PHY_CODED (BLE_HCI_LE_PHY_CODED)
|
||||
|
||||
/* PHY bitmasks (compatible with HCI) */
|
||||
#define BLE_PHY_MASK_1M (BLE_HCI_LE_PHY_1M_PREF_MASK)
|
||||
#define BLE_PHY_MASK_2M (BLE_HCI_LE_PHY_2M_PREF_MASK)
|
||||
#define BLE_PHY_MASK_CODED (BLE_HCI_LE_PHY_CODED_PREF_MASK)
|
||||
|
||||
#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) || MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY))
|
||||
uint32_t ble_phy_mode_pdu_start_off(int phy);
|
||||
void ble_phy_mode_set(uint8_t tx_phy_mode, uint8_t rx_phy_mode);
|
||||
#else
|
||||
#define ble_phy_mode_pdu_start_off(phy) (40)
|
||||
|
||||
#endif
|
||||
|
||||
int ble_phy_get_cur_phy(void);
|
||||
static inline int ble_ll_phy_to_phy_mode(int phy, int phy_options)
|
||||
{
|
||||
int phy_mode;
|
||||
|
||||
/*
|
||||
* 'phy' value can be used as 'phy_mode' value unless S=2 coding is explicitly
|
||||
* required. By default we'll use S=2 for Coded.
|
||||
*/
|
||||
phy_mode = phy;
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
|
||||
if (phy == BLE_PHY_CODED && phy_options == BLE_HCI_LE_PHY_CODED_S2_PREF) {
|
||||
phy_mode = BLE_PHY_MODE_CODED_500KBPS;
|
||||
}
|
||||
#endif
|
||||
|
||||
return phy_mode;
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_DTM)
|
||||
void ble_phy_enable_dtm(void);
|
||||
void ble_phy_disable_dtm(void);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* H_BLE_PHY_ */
|
||||
@@ -0,0 +1,96 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef H_BLE_PHY_TRACE_
|
||||
#define H_BLE_PHY_TRACE_
|
||||
|
||||
#include "nimble/porting/nimble/include/os/os_trace_api.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define BLE_PHY_TRACE_ID_START_TX 0
|
||||
#define BLE_PHY_TRACE_ID_START_RX 1
|
||||
#define BLE_PHY_TRACE_ID_DISABLE 2
|
||||
|
||||
#if MYNEWT_VAL(BLE_PHY_SYSVIEW)
|
||||
|
||||
extern uint32_t ble_phy_trace_off;
|
||||
|
||||
void ble_phy_trace_init(void);
|
||||
|
||||
static inline void
|
||||
ble_phy_trace_void(unsigned id)
|
||||
{
|
||||
os_trace_api_void(ble_phy_trace_off + id);
|
||||
}
|
||||
|
||||
static inline void
|
||||
ble_phy_trace_u32(unsigned id, uint32_t p1)
|
||||
{
|
||||
os_trace_api_u32(ble_phy_trace_off + id, p1);
|
||||
}
|
||||
|
||||
static inline void
|
||||
ble_phy_trace_u32x2(unsigned id, uint32_t p1, uint32_t p2)
|
||||
{
|
||||
os_trace_api_u32x2(ble_phy_trace_off + id, p1, p2);
|
||||
}
|
||||
|
||||
static inline void
|
||||
ble_phy_trace_u32x3(unsigned id, uint32_t p1, uint32_t p2, uint32_t p3)
|
||||
{
|
||||
os_trace_api_u32x3(ble_phy_trace_off + id, p1, p2, p3);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static inline void
|
||||
ble_phy_trace_init(void)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void
|
||||
ble_phy_trace_void(unsigned id)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void
|
||||
ble_phy_trace_u32(unsigned id, uint32_t p1)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void
|
||||
ble_phy_trace_u32x2(unsigned id, uint32_t p1, uint32_t p2)
|
||||
{
|
||||
}
|
||||
|
||||
static inline void
|
||||
ble_phy_trace_u32x3(unsigned id, uint32_t p1, uint32_t p2, uint32_t p3)
|
||||
{
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* H_BLE_PHY_TRACE_ */
|
||||
1723
lib/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll.c
Normal file
1723
lib/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll.c
Normal file
File diff suppressed because it is too large
Load Diff
5143
lib/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_adv.c
Normal file
5143
lib/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_adv.c
Normal file
File diff suppressed because it is too large
Load Diff
4279
lib/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_conn.c
Normal file
4279
lib/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_conn.c
Normal file
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,226 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef H_BLE_LL_CONN_PRIV_
|
||||
#define H_BLE_LL_CONN_PRIV_
|
||||
|
||||
#include "../include/controller/ble_ll_conn.h"
|
||||
#include "../include/controller/ble_ll_hci.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Definitions for min/max RX/TX time/bytes values allowed for connections.
|
||||
* Source: Core 5.0 specification, Vol 6, Part B, section 4.5.10
|
||||
*/
|
||||
#define BLE_LL_CONN_SUPP_TIME_MIN (328) /* usecs */
|
||||
#define BLE_LL_CONN_SUPP_TIME_MAX (17040) /* usecs */
|
||||
#define BLE_LL_CONN_SUPP_TIME_MIN_UNCODED (328) /* usecs */
|
||||
#define BLE_LL_CONN_SUPP_TIME_MAX_UNCODED (2120) /* usecs */
|
||||
#define BLE_LL_CONN_SUPP_TIME_MIN_CODED (2704) /* usecs */
|
||||
#define BLE_LL_CONN_SUPP_TIME_MAX_CODED (17040) /* usecs */
|
||||
#define BLE_LL_CONN_SUPP_BYTES_MIN (27) /* bytes */
|
||||
#define BLE_LL_CONN_SUPP_BYTES_MAX (251) /* bytes */
|
||||
|
||||
/* Connection event timing */
|
||||
#define BLE_LL_CONN_INITIAL_OFFSET (1250)
|
||||
#define BLE_LL_CONN_ITVL_USECS (1250)
|
||||
#define BLE_LL_CONN_TX_WIN_USECS (1250)
|
||||
#define BLE_LL_CONN_TX_OFF_USECS (1250)
|
||||
#define BLE_LL_CONN_CE_USECS (625)
|
||||
#define BLE_LL_CONN_TX_WIN_MIN (1) /* in tx win units */
|
||||
#define BLE_LL_CONN_SLAVE_LATENCY_MAX (499)
|
||||
|
||||
/* Connection handle range */
|
||||
#define BLE_LL_CONN_MAX_CONN_HANDLE (0x0EFF)
|
||||
|
||||
/* Offset (in bytes) of advertising address in connect request */
|
||||
#define BLE_LL_CONN_REQ_ADVA_OFF (BLE_LL_PDU_HDR_LEN + BLE_DEV_ADDR_LEN)
|
||||
|
||||
/* Default authenticated payload timeout (30 seconds; in 10 msecs increments) */
|
||||
#define BLE_LL_CONN_DEF_AUTH_PYLD_TMO (3000)
|
||||
#define BLE_LL_CONN_AUTH_PYLD_OS_TMO(x) ble_npl_time_ms_to_ticks32((x) * 10)
|
||||
|
||||
/* Global Link Layer connection parameters */
|
||||
struct ble_ll_conn_global_params
|
||||
{
|
||||
uint8_t master_chan_map[BLE_LL_CONN_CHMAP_LEN];
|
||||
uint8_t num_used_chans;
|
||||
uint8_t supp_max_tx_octets;
|
||||
uint8_t supp_max_rx_octets;
|
||||
uint8_t conn_init_max_tx_octets;
|
||||
uint8_t sugg_tx_octets;
|
||||
uint16_t sugg_tx_time;
|
||||
uint16_t conn_init_max_tx_time;
|
||||
uint16_t conn_init_max_tx_time_uncoded;
|
||||
uint16_t conn_init_max_tx_time_coded;
|
||||
uint16_t supp_max_tx_time;
|
||||
uint16_t supp_max_rx_time;
|
||||
};
|
||||
extern struct ble_ll_conn_global_params g_ble_ll_conn_params;
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER)
|
||||
struct ble_ll_conn_sync_transfer_params
|
||||
{
|
||||
uint32_t sync_timeout_us;
|
||||
uint16_t max_skip;
|
||||
uint8_t mode;
|
||||
};
|
||||
extern struct ble_ll_conn_sync_transfer_params g_ble_ll_conn_sync_transfer_params;
|
||||
#endif
|
||||
|
||||
/* Some data structures used by other LL routines */
|
||||
SLIST_HEAD(ble_ll_conn_active_list, ble_ll_conn_sm);
|
||||
STAILQ_HEAD(ble_ll_conn_free_list, ble_ll_conn_sm);
|
||||
extern struct ble_ll_conn_active_list g_ble_ll_conn_active_list;
|
||||
extern struct ble_ll_conn_free_list g_ble_ll_conn_free_list;
|
||||
|
||||
/* Pointer to connection state machine we are trying to create */
|
||||
extern struct ble_ll_conn_sm *g_ble_ll_conn_create_sm;
|
||||
|
||||
/* Generic interface */
|
||||
struct ble_ll_len_req;
|
||||
struct ble_mbuf_hdr;
|
||||
struct ble_ll_adv_sm;
|
||||
|
||||
struct hci_create_conn
|
||||
{
|
||||
uint16_t scan_itvl;
|
||||
uint16_t scan_window;
|
||||
uint8_t filter_policy;
|
||||
uint8_t peer_addr_type;
|
||||
uint8_t peer_addr[BLE_DEV_ADDR_LEN];
|
||||
uint8_t own_addr_type;
|
||||
uint16_t conn_itvl_min;
|
||||
uint16_t conn_itvl_max;
|
||||
uint16_t conn_latency;
|
||||
uint16_t supervision_timeout;
|
||||
uint16_t min_ce_len;
|
||||
uint16_t max_ce_len;
|
||||
};
|
||||
|
||||
void ble_ll_conn_sm_new(struct ble_ll_conn_sm *connsm);
|
||||
void ble_ll_conn_end(struct ble_ll_conn_sm *connsm, uint8_t ble_err);
|
||||
void ble_ll_conn_enqueue_pkt(struct ble_ll_conn_sm *connsm, struct os_mbuf *om,
|
||||
uint8_t hdr_byte, uint8_t length);
|
||||
struct ble_ll_conn_sm *ble_ll_conn_sm_get(void);
|
||||
void ble_ll_conn_master_init(struct ble_ll_conn_sm *connsm,
|
||||
struct hci_create_conn *hcc);
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
|
||||
void ble_ll_conn_ext_master_init(struct ble_ll_conn_sm *connsm,
|
||||
struct hci_ext_create_conn *hcc);
|
||||
|
||||
void ble_ll_conn_ext_set_params(struct ble_ll_conn_sm *connsm,
|
||||
struct hci_ext_conn_params *hcc_params,
|
||||
int phy);
|
||||
#endif
|
||||
|
||||
struct ble_ll_conn_sm *ble_ll_conn_find_active_conn(uint16_t handle);
|
||||
void ble_ll_conn_update_eff_data_len(struct ble_ll_conn_sm *connsm);
|
||||
|
||||
/* Advertising interface */
|
||||
int ble_ll_conn_slave_start(uint8_t *rxbuf, uint8_t pat,
|
||||
struct ble_mbuf_hdr *rxhdr, bool force_csa2);
|
||||
|
||||
/* Link Layer interface */
|
||||
void ble_ll_conn_module_init(void);
|
||||
void ble_ll_conn_set_global_chanmap(uint8_t num_used_chans, const uint8_t *chanmap);
|
||||
void ble_ll_conn_module_reset(void);
|
||||
void ble_ll_conn_tx_pkt_in(struct os_mbuf *om, uint16_t handle, uint16_t len);
|
||||
int ble_ll_conn_rx_isr_start(struct ble_mbuf_hdr *rxhdr, uint32_t aa);
|
||||
int ble_ll_conn_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr);
|
||||
void ble_ll_conn_rx_data_pdu(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr);
|
||||
void ble_ll_init_rx_pkt_in(uint8_t pdu_type, uint8_t *rxbuf,
|
||||
struct ble_mbuf_hdr *ble_hdr);
|
||||
int ble_ll_init_rx_isr_start(uint8_t pdu_type, struct ble_mbuf_hdr *ble_hdr);
|
||||
int ble_ll_init_rx_isr_end(uint8_t *rxbuf, uint8_t crcok,
|
||||
struct ble_mbuf_hdr *ble_hdr);
|
||||
void ble_ll_conn_wfr_timer_exp(void);
|
||||
void ble_ll_conn_init_wfr_timer_exp(void);
|
||||
int ble_ll_conn_is_lru(struct ble_ll_conn_sm *s1, struct ble_ll_conn_sm *s2);
|
||||
uint32_t ble_ll_conn_get_ce_end_time(void);
|
||||
void ble_ll_conn_event_halt(void);
|
||||
void ble_ll_conn_reset_pending_aux_conn_rsp(void);
|
||||
bool ble_ll_conn_init_pending_aux_conn_rsp(void);
|
||||
/* HCI */
|
||||
void ble_ll_disconn_comp_event_send(struct ble_ll_conn_sm *connsm,
|
||||
uint8_t reason);
|
||||
void ble_ll_auth_pyld_tmo_event_send(struct ble_ll_conn_sm *connsm);
|
||||
int ble_ll_conn_hci_disconnect_cmd(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_conn_hci_rd_rem_ver_cmd(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_conn_create(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_conn_hci_update(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_conn_hci_set_chan_class(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_conn_hci_param_rr(const uint8_t *cmdbuf, uint8_t len,
|
||||
uint8_t *rspbuf, uint8_t *rsplen);
|
||||
int ble_ll_conn_hci_param_nrr(const uint8_t *cmdbuf, uint8_t len,
|
||||
uint8_t *rspbuf, uint8_t *rsplen);
|
||||
int ble_ll_conn_create_cancel(ble_ll_hci_post_cmd_complete_cb *post_cmd_cb);
|
||||
void ble_ll_conn_num_comp_pkts_event_send(struct ble_ll_conn_sm *connsm);
|
||||
void ble_ll_conn_comp_event_send(struct ble_ll_conn_sm *connsm, uint8_t status,
|
||||
uint8_t *evbuf, struct ble_ll_adv_sm *advsm);
|
||||
void ble_ll_conn_timeout(struct ble_ll_conn_sm *connsm, uint8_t ble_err);
|
||||
int ble_ll_conn_hci_chk_conn_params(uint16_t itvl_min, uint16_t itvl_max,
|
||||
uint16_t latency, uint16_t spvn_tmo);
|
||||
int ble_ll_conn_hci_read_rem_features(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_conn_hci_rd_rssi(const uint8_t *cmdbuf, uint8_t len, uint8_t *rspbuf,
|
||||
uint8_t *rsplen);
|
||||
int ble_ll_conn_hci_rd_chan_map(const uint8_t *cmdbuf, uint8_t len,
|
||||
uint8_t *rspbuf, uint8_t *rsplen);
|
||||
int ble_ll_conn_hci_set_data_len(const uint8_t *cmdbuf, uint8_t len,
|
||||
uint8_t *rspbuf, uint8_t *rsplen);
|
||||
int ble_ll_conn_hci_le_start_encrypt(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_conn_hci_le_ltk_reply(const uint8_t *cmdbuf, uint8_t len,
|
||||
uint8_t *rspbuf, uint8_t *rsplen);
|
||||
int ble_ll_conn_hci_le_ltk_neg_reply(const uint8_t *cmdbuf, uint8_t len,
|
||||
uint8_t *rspbuf, uint8_t *rsplen);
|
||||
int ble_ll_conn_hci_wr_auth_pyld_tmo(const uint8_t *cmdbuf, uint8_t len,
|
||||
uint8_t *rspbuf, uint8_t *rsplen);
|
||||
int ble_ll_conn_hci_rd_auth_pyld_tmo(const uint8_t *cmdbuf, uint8_t len,
|
||||
uint8_t *rspbuf, uint8_t *rsplen);
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_PING)
|
||||
void ble_ll_conn_auth_pyld_timer_start(struct ble_ll_conn_sm *connsm);
|
||||
#else
|
||||
#define ble_ll_conn_auth_pyld_timer_start(x)
|
||||
#endif
|
||||
|
||||
int ble_ll_hci_cmd_rx(uint8_t *cmd, void *arg);
|
||||
int ble_ll_hci_acl_rx(struct os_mbuf *om, void *arg);
|
||||
|
||||
int ble_ll_conn_hci_le_rd_phy(const uint8_t *cmdbuf, uint8_t len,
|
||||
uint8_t *rsp, uint8_t *rsplen);
|
||||
int ble_ll_conn_hci_le_set_phy(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_conn_chk_phy_upd_start(struct ble_ll_conn_sm *connsm);
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
|
||||
int ble_ll_ext_conn_create(const uint8_t *cmdbuf, uint8_t cmdlen);
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER)
|
||||
int ble_ll_set_sync_transfer_params(const uint8_t *cmdbuf, uint8_t len,
|
||||
uint8_t *rspbuf, uint8_t *rsplen);
|
||||
int ble_ll_set_default_sync_transfer_params(const uint8_t *cmdbuf, uint8_t len);
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* H_BLE_LL_CONN_PRIV_ */
|
||||
2748
lib/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_ctrl.c
Normal file
2748
lib/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_ctrl.c
Normal file
File diff suppressed because it is too large
Load Diff
728
lib/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_dtm.c
Normal file
728
lib/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_dtm.c
Normal file
@@ -0,0 +1,728 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
#ifndef ESP_PLATFORM
|
||||
|
||||
#include "nimble/porting/nimble/include/syscfg/syscfg.h"
|
||||
#include "nimble/porting/nimble/include/sysinit/sysinit.h"
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_DTM)
|
||||
|
||||
#include <assert.h>
|
||||
#include "nimble/porting/nimble/include/os/os.h"
|
||||
#include "nimble/nimble/porting/nimble/include/stats/stats.h"
|
||||
#include "../include/controller/ble_ll.h"
|
||||
#include "../include/controller/ble_phy.h"
|
||||
#include "../include/controller/ble_ll_sched.h"
|
||||
#include "../include/controller/ble_ll_rfmgmt.h"
|
||||
#include "ble_ll_dtm_priv.h"
|
||||
|
||||
STATS_SECT_START(ble_ll_dtm_stats)
|
||||
STATS_SECT_ENTRY(rx_count)
|
||||
STATS_SECT_ENTRY(tx_failed)
|
||||
STATS_SECT_ENTRY(rx_failed)
|
||||
STATS_SECT_END
|
||||
STATS_SECT_DECL(ble_ll_dtm_stats) ble_ll_dtm_stats;
|
||||
|
||||
STATS_NAME_START(ble_ll_dtm_stats)
|
||||
STATS_NAME(ble_ll_dtm_stats, rx_count)
|
||||
STATS_NAME(ble_ll_dtm_stats, tx_failed)
|
||||
STATS_NAME(ble_ll_dtm_stats, rx_failed)
|
||||
STATS_NAME_END(ble_phy_stats)
|
||||
|
||||
struct dtm_ctx {
|
||||
uint8_t payload_packet;
|
||||
uint8_t itvl_rem_usec;
|
||||
uint16_t num_of_packets;
|
||||
uint32_t itvl_ticks;
|
||||
#if MYNEWT_VAL(BLE_LL_DTM_EXTENSIONS)
|
||||
uint16_t num_of_packets_max;
|
||||
#endif
|
||||
int active;
|
||||
uint8_t rf_channel;
|
||||
uint8_t phy_mode;
|
||||
struct os_mbuf *om;
|
||||
struct ble_npl_event evt;
|
||||
struct ble_ll_sched_item sch;
|
||||
uint32_t pdu_start_ticks;
|
||||
uint8_t pdu_start_usecs;
|
||||
};
|
||||
|
||||
static struct dtm_ctx g_ble_ll_dtm_ctx;
|
||||
|
||||
static const uint8_t g_ble_ll_dtm_prbs9_data[] =
|
||||
{
|
||||
0xff, 0xc1, 0xfb, 0xe8, 0x4c, 0x90, 0x72, 0x8b,
|
||||
0xe7, 0xb3, 0x51, 0x89, 0x63, 0xab, 0x23, 0x23,
|
||||
0x02, 0x84, 0x18, 0x72, 0xaa, 0x61, 0x2f, 0x3b,
|
||||
0x51, 0xa8, 0xe5, 0x37, 0x49, 0xfb, 0xc9, 0xca,
|
||||
0x0c, 0x18, 0x53, 0x2c, 0xfd, 0x45, 0xe3, 0x9a,
|
||||
0xe6, 0xf1, 0x5d, 0xb0, 0xb6, 0x1b, 0xb4, 0xbe,
|
||||
0x2a, 0x50, 0xea, 0xe9, 0x0e, 0x9c, 0x4b, 0x5e,
|
||||
0x57, 0x24, 0xcc, 0xa1, 0xb7, 0x59, 0xb8, 0x87,
|
||||
0xff, 0xe0, 0x7d, 0x74, 0x26, 0x48, 0xb9, 0xc5,
|
||||
0xf3, 0xd9, 0xa8, 0xc4, 0xb1, 0xd5, 0x91, 0x11,
|
||||
0x01, 0x42, 0x0c, 0x39, 0xd5, 0xb0, 0x97, 0x9d,
|
||||
0x28, 0xd4, 0xf2, 0x9b, 0xa4, 0xfd, 0x64, 0x65,
|
||||
0x06, 0x8c, 0x29, 0x96, 0xfe, 0xa2, 0x71, 0x4d,
|
||||
0xf3, 0xf8, 0x2e, 0x58, 0xdb, 0x0d, 0x5a, 0x5f,
|
||||
0x15, 0x28, 0xf5, 0x74, 0x07, 0xce, 0x25, 0xaf,
|
||||
0x2b, 0x12, 0xe6, 0xd0, 0xdb, 0x2c, 0xdc, 0xc3,
|
||||
0x7f, 0xf0, 0x3e, 0x3a, 0x13, 0xa4, 0xdc, 0xe2,
|
||||
0xf9, 0x6c, 0x54, 0xe2, 0xd8, 0xea, 0xc8, 0x88,
|
||||
0x00, 0x21, 0x86, 0x9c, 0x6a, 0xd8, 0xcb, 0x4e,
|
||||
0x14, 0x6a, 0xf9, 0x4d, 0xd2, 0x7e, 0xb2, 0x32,
|
||||
0x03, 0xc6, 0x14, 0x4b, 0x7f, 0xd1, 0xb8, 0xa6,
|
||||
0x79, 0x7c, 0x17, 0xac, 0xed, 0x06, 0xad, 0xaf,
|
||||
0x0a, 0x94, 0x7a, 0xba, 0x03, 0xe7, 0x92, 0xd7,
|
||||
0x15, 0x09, 0x73, 0xe8, 0x6d, 0x16, 0xee, 0xe1,
|
||||
0x3f, 0x78, 0x1f, 0x9d, 0x09, 0x52, 0x6e, 0xf1,
|
||||
0x7c, 0x36, 0x2a, 0x71, 0x6c, 0x75, 0x64, 0x44,
|
||||
0x80, 0x10, 0x43, 0x4e, 0x35, 0xec, 0x65, 0x27,
|
||||
0x0a, 0xb5, 0xfc, 0x26, 0x69, 0x3f, 0x59, 0x99,
|
||||
0x01, 0x63, 0x8a, 0xa5, 0xbf, 0x68, 0x5c, 0xd3,
|
||||
0x3c, 0xbe, 0x0b, 0xd6, 0x76, 0x83, 0xd6, 0x57,
|
||||
0x05, 0x4a, 0x3d, 0xdd, 0x81, 0x73, 0xc9, 0xeb,
|
||||
0x8a, 0x84, 0x39, 0xf4, 0x36, 0x0b, 0xf7
|
||||
};
|
||||
|
||||
static const uint8_t g_ble_ll_dtm_prbs15_data[] =
|
||||
{
|
||||
0xff, 0x7f, 0xf0, 0x3e, 0x3a, 0x13, 0xa4, 0xdc,
|
||||
0xe2, 0xf9, 0x6c, 0x54, 0xe2, 0xd8, 0xea, 0xc8,
|
||||
0x88, 0x00, 0x21, 0x86, 0x9c, 0x6a, 0xd8, 0xcb,
|
||||
0x4e, 0x14, 0x6a, 0xf9, 0x4d, 0xd2, 0x7e, 0xb2,
|
||||
0x32, 0x03, 0xc6, 0x14, 0x4b, 0x7f, 0xd1, 0xb8,
|
||||
0xa6, 0x79, 0x7c, 0x17, 0xac, 0xed, 0x06, 0xad,
|
||||
0xaf, 0x0a, 0x94, 0x7a, 0xba, 0x03, 0xe7, 0x92,
|
||||
0xd7, 0x15, 0x09, 0x73, 0xe8, 0x6d, 0x16, 0xee,
|
||||
0xe1, 0x3f, 0x78, 0x1f, 0x9d, 0x09, 0x52, 0x6e,
|
||||
0xf1, 0x7c, 0x36, 0x2a, 0x71, 0x6c, 0x75, 0x64,
|
||||
0x44, 0x80, 0x10, 0x43, 0x4e, 0x35, 0xec, 0x65,
|
||||
0x27, 0x0a, 0xb5, 0xfc, 0x26, 0x69, 0x3f, 0x59,
|
||||
0x99, 0x01, 0x63, 0x8a, 0xa5, 0xbf, 0x68, 0x5c,
|
||||
0xd3, 0x3c, 0xbe, 0x0b, 0xd6, 0x76, 0x83, 0xd6,
|
||||
0x57, 0x05, 0x4a, 0x3d, 0xdd, 0x81, 0x73, 0xc9,
|
||||
0xeb, 0x8a, 0x84, 0x39, 0xf4, 0x36, 0x0b, 0xf7,
|
||||
0xf0, 0x1f, 0xbc, 0x8f, 0xce, 0x04, 0x29, 0xb7,
|
||||
0x78, 0x3e, 0x1b, 0x95, 0x38, 0xb6, 0x3a, 0x32,
|
||||
0x22, 0x40, 0x88, 0x21, 0xa7, 0x1a, 0xf6, 0xb2,
|
||||
0x13, 0x85, 0x5a, 0x7e, 0x93, 0xb4, 0x9f, 0xac,
|
||||
0xcc, 0x80, 0x31, 0xc5, 0xd2, 0x5f, 0x34, 0xae,
|
||||
0x69, 0x1e, 0xdf, 0x05, 0x6b, 0xbb, 0x41, 0xeb,
|
||||
0xab, 0x02, 0xa5, 0x9e, 0xee, 0xc0, 0xb9, 0xe4,
|
||||
0x75, 0x45, 0xc2, 0x1c, 0x7a, 0x9b, 0x85, 0x7b,
|
||||
0xf8, 0x0f, 0xde, 0x47, 0x67, 0x82, 0x94, 0x5b,
|
||||
0x3c, 0x9f, 0x8d, 0x4a, 0x1c, 0x5b, 0x1d, 0x19,
|
||||
0x11, 0x20, 0xc4, 0x90, 0x53, 0x0d, 0x7b, 0xd9,
|
||||
0x89, 0x42, 0x2d, 0xbf, 0x49, 0xda, 0x4f, 0x56,
|
||||
0x66, 0xc0, 0x98, 0x62, 0xe9, 0x2f, 0x1a, 0xd7,
|
||||
0x34, 0x8f, 0xef, 0x82, 0xb5, 0xdd, 0xa0, 0xf5,
|
||||
0x55, 0x81, 0x52, 0x4f, 0x77, 0xe0, 0x5c, 0xf2,
|
||||
0xba, 0x22, 0x61, 0x0e, 0xbd, 0xcd, 0xc2
|
||||
};
|
||||
|
||||
static const uint8_t channel_rf_to_index[] = {
|
||||
37, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 38, 11 ,12, 13, 14, 15,
|
||||
16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33,
|
||||
34, 35, 36, 39
|
||||
};
|
||||
|
||||
#define BLE_DTM_SYNC_WORD (0x71764129)
|
||||
#define BLE_DTM_CRC (0x555555)
|
||||
|
||||
static void ble_ll_dtm_ctx_free(struct dtm_ctx * ctx);
|
||||
|
||||
static void
|
||||
ble_ll_dtm_set_next(struct dtm_ctx *ctx)
|
||||
{
|
||||
struct ble_ll_sched_item *sch = &ctx->sch;
|
||||
|
||||
ctx->pdu_start_ticks += ctx->itvl_ticks;
|
||||
ctx->pdu_start_usecs += ctx->itvl_rem_usec;
|
||||
if (ctx->pdu_start_usecs >= 31) {
|
||||
ctx->pdu_start_ticks++;
|
||||
ctx->pdu_start_usecs -= 31;
|
||||
}
|
||||
|
||||
sch->start_time = ctx->pdu_start_ticks;
|
||||
sch->remainder = ctx->pdu_start_usecs;
|
||||
|
||||
sch->start_time -= g_ble_ll_sched_offset_ticks;
|
||||
}
|
||||
|
||||
static void
|
||||
ble_ll_dtm_ev_tx_resched_cb(struct ble_npl_event *evt) {
|
||||
/* It is called in LL context */
|
||||
struct dtm_ctx *ctx = ble_npl_event_get_arg(evt);
|
||||
int rc;
|
||||
os_sr_t sr;
|
||||
|
||||
OS_ENTER_CRITICAL(sr);
|
||||
if (!ctx->active || !ctx->om) {
|
||||
OS_EXIT_CRITICAL(sr);
|
||||
return;
|
||||
}
|
||||
OS_EXIT_CRITICAL(sr);
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_DTM_EXTENSIONS)
|
||||
if (g_ble_ll_dtm_ctx.num_of_packets_max &&
|
||||
(g_ble_ll_dtm_ctx.num_of_packets == g_ble_ll_dtm_ctx.num_of_packets_max)) {
|
||||
/*
|
||||
* XXX do not send more packets, but also do not stop DTM - it shall be
|
||||
* stopped as usual by HCI command since there is no standard way to
|
||||
* signal end of test to host.
|
||||
*/
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
ble_ll_dtm_set_next(ctx);
|
||||
rc = ble_ll_sched_dtm(&ctx->sch);
|
||||
BLE_LL_ASSERT(rc == 0);
|
||||
}
|
||||
|
||||
static int ble_ll_dtm_rx_start(void);
|
||||
|
||||
static void
|
||||
ble_ll_dtm_ev_rx_restart_cb(struct ble_npl_event *evt) {
|
||||
if (ble_ll_dtm_rx_start() != 0) {
|
||||
ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_dtm_ctx.evt);
|
||||
STATS_INC(ble_ll_dtm_stats, rx_failed);
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ble_ll_dtm_tx_done(void *arg)
|
||||
{
|
||||
struct dtm_ctx *ctx;
|
||||
|
||||
ctx = arg;
|
||||
if (!ctx->active) {
|
||||
return;
|
||||
}
|
||||
|
||||
g_ble_ll_dtm_ctx.num_of_packets++;
|
||||
|
||||
/* Reschedule event in LL context */
|
||||
ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &ctx->evt);
|
||||
|
||||
ble_ll_state_set(BLE_LL_STATE_STANDBY);
|
||||
}
|
||||
|
||||
static int
|
||||
ble_ll_dtm_tx_sched_cb(struct ble_ll_sched_item *sch)
|
||||
{
|
||||
struct dtm_ctx *ctx = sch->cb_arg;
|
||||
int rc;
|
||||
|
||||
if (!ctx->active) {
|
||||
return BLE_LL_SCHED_STATE_DONE;
|
||||
}
|
||||
|
||||
rc = ble_phy_setchan(channel_rf_to_index[ctx->rf_channel],
|
||||
BLE_DTM_SYNC_WORD, BLE_DTM_CRC);
|
||||
if (rc != 0) {
|
||||
BLE_LL_ASSERT(0);
|
||||
return BLE_LL_SCHED_STATE_DONE;
|
||||
}
|
||||
|
||||
#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) || MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY))
|
||||
ble_phy_mode_set(ctx->phy_mode, ctx->phy_mode);
|
||||
#endif
|
||||
ble_phy_set_txend_cb(ble_ll_dtm_tx_done, ctx);
|
||||
ble_phy_txpwr_set(0);
|
||||
|
||||
sch->start_time += g_ble_ll_sched_offset_ticks;
|
||||
|
||||
rc = ble_phy_tx_set_start_time(sch->start_time, sch->remainder);
|
||||
if (rc) {
|
||||
goto resched;
|
||||
}
|
||||
|
||||
rc = ble_phy_tx(ble_ll_tx_mbuf_pducb, ctx->om, BLE_PHY_TRANSITION_NONE);
|
||||
if (rc) {
|
||||
goto resched;
|
||||
}
|
||||
|
||||
ble_ll_state_set(BLE_LL_STATE_DTM);
|
||||
|
||||
return BLE_LL_SCHED_STATE_DONE;
|
||||
|
||||
resched:
|
||||
/* Reschedule from LL task if late for this PDU */
|
||||
ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &ctx->evt);
|
||||
|
||||
STATS_INC(ble_ll_dtm_stats, tx_failed);
|
||||
|
||||
return BLE_LL_SCHED_STATE_DONE;
|
||||
}
|
||||
|
||||
static void
|
||||
ble_ll_dtm_calculate_itvl(struct dtm_ctx *ctx, uint8_t len,
|
||||
uint16_t cmd_interval, int phy_mode)
|
||||
{
|
||||
uint32_t l;
|
||||
uint32_t itvl_usec;
|
||||
uint32_t itvl_ticks;
|
||||
|
||||
/* Calculate interval as per spec Bluetooth 5.0 Vol 6. Part F, 4.1.6 */
|
||||
l = ble_ll_pdu_tx_time_get(len + BLE_LL_PDU_HDR_LEN, phy_mode);
|
||||
itvl_usec = ((l + 249 + 624) / 625) * 625;
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_DTM_EXTENSIONS)
|
||||
if (cmd_interval > itvl_usec) {
|
||||
itvl_usec = cmd_interval;
|
||||
}
|
||||
#endif
|
||||
|
||||
itvl_ticks = os_cputime_usecs_to_ticks(itvl_usec);
|
||||
ctx->itvl_rem_usec = (itvl_usec - os_cputime_ticks_to_usecs(itvl_ticks));
|
||||
if (ctx->itvl_rem_usec == 31) {
|
||||
ctx->itvl_rem_usec = 0;
|
||||
++itvl_ticks;
|
||||
}
|
||||
ctx->itvl_ticks = itvl_ticks;
|
||||
}
|
||||
|
||||
static int
|
||||
ble_ll_dtm_tx_create_ctx(uint8_t packet_payload, uint8_t len,
|
||||
uint8_t rf_channel, uint8_t phy_mode,
|
||||
uint16_t cmd_interval, uint16_t cmd_pkt_count)
|
||||
{
|
||||
int rc = 0;
|
||||
uint8_t byte_pattern;
|
||||
struct ble_mbuf_hdr *ble_hdr;
|
||||
struct os_mbuf *m;
|
||||
struct dtm_ctx *ctx = &g_ble_ll_dtm_ctx;
|
||||
struct ble_ll_sched_item *sch = &ctx->sch;
|
||||
|
||||
/* MSYS is big enough to get continues memory */
|
||||
m = os_msys_get_pkthdr(len, sizeof(struct ble_mbuf_hdr));
|
||||
ctx->om = m;
|
||||
BLE_LL_ASSERT(g_ble_ll_dtm_ctx.om);
|
||||
|
||||
ctx->phy_mode = phy_mode;
|
||||
ctx->rf_channel = rf_channel;
|
||||
ctx->num_of_packets = 0;
|
||||
#if MYNEWT_VAL(BLE_LL_DTM_EXTENSIONS)
|
||||
ctx->num_of_packets_max = cmd_pkt_count;
|
||||
#endif
|
||||
|
||||
/* Set BLE transmit header */
|
||||
ble_hdr = BLE_MBUF_HDR_PTR(m);
|
||||
ble_hdr->txinfo.flags = 0;
|
||||
ble_hdr->txinfo.offset = 0;
|
||||
ble_hdr->txinfo.pyld_len = len;
|
||||
ble_hdr->txinfo.hdr_byte = packet_payload;
|
||||
|
||||
switch(packet_payload) {
|
||||
case 0x00:
|
||||
if (os_mbuf_copyinto(m, 0, &g_ble_ll_dtm_prbs9_data, len)) {
|
||||
return 1;
|
||||
}
|
||||
goto schedule;
|
||||
case 0x01:
|
||||
byte_pattern = 0x0F;
|
||||
break;
|
||||
case 0x02:
|
||||
byte_pattern = 0x55;
|
||||
break;
|
||||
case 0x03:
|
||||
if (os_mbuf_copyinto(m, 0, &g_ble_ll_dtm_prbs15_data, len)) {
|
||||
return 1;
|
||||
}
|
||||
goto schedule;
|
||||
case 0x04:
|
||||
byte_pattern = 0xFF;
|
||||
break;
|
||||
case 0x05:
|
||||
byte_pattern = 0x00;
|
||||
break;
|
||||
case 0x06:
|
||||
byte_pattern = 0xF0;
|
||||
break;
|
||||
case 0x07:
|
||||
byte_pattern = 0xAA;
|
||||
break;
|
||||
default:
|
||||
return 1;
|
||||
}
|
||||
|
||||
for (rc = 0; rc < len; rc++) {
|
||||
if (os_mbuf_copyinto(m, rc, &byte_pattern, 1)) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
schedule:
|
||||
ble_phy_enable_dtm();
|
||||
|
||||
sch->sched_cb = ble_ll_dtm_tx_sched_cb;
|
||||
sch->cb_arg = ctx;
|
||||
sch->sched_type = BLE_LL_SCHED_TYPE_DTM;
|
||||
|
||||
/* Prepare os_event */
|
||||
ble_npl_event_init(&ctx->evt, ble_ll_dtm_ev_tx_resched_cb, ctx);
|
||||
|
||||
ble_ll_dtm_calculate_itvl(ctx, len, cmd_interval, phy_mode);
|
||||
|
||||
ctx->pdu_start_ticks = ble_ll_rfmgmt_enable_now();
|
||||
ctx->pdu_start_usecs = 0;
|
||||
ble_ll_dtm_set_next(ctx);
|
||||
|
||||
/* Set some start point for TX packets */
|
||||
rc = ble_ll_sched_dtm(sch);
|
||||
BLE_LL_ASSERT(rc == 0);
|
||||
|
||||
g_ble_ll_dtm_ctx.active = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ble_ll_dtm_rx_start(void)
|
||||
{
|
||||
os_sr_t sr;
|
||||
int rc;
|
||||
|
||||
rc = ble_phy_setchan(channel_rf_to_index[g_ble_ll_dtm_ctx.rf_channel],
|
||||
BLE_DTM_SYNC_WORD, BLE_DTM_CRC);
|
||||
if (rc) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
#if (MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY) || MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY))
|
||||
ble_phy_mode_set(g_ble_ll_dtm_ctx.phy_mode, g_ble_ll_dtm_ctx.phy_mode);
|
||||
#endif
|
||||
|
||||
OS_ENTER_CRITICAL(sr);
|
||||
rc = ble_phy_rx_set_start_time(os_cputime_get32(), 0);
|
||||
OS_EXIT_CRITICAL(sr);
|
||||
if (rc && rc != BLE_PHY_ERR_RX_LATE) {
|
||||
return rc;
|
||||
}
|
||||
|
||||
ble_ll_state_set(BLE_LL_STATE_DTM);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
ble_ll_dtm_rx_sched_cb(struct ble_ll_sched_item *sch)
|
||||
{
|
||||
if (ble_ll_dtm_rx_start() != 0) {
|
||||
ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_dtm_ctx.evt);
|
||||
STATS_INC(ble_ll_dtm_stats, rx_failed);
|
||||
}
|
||||
|
||||
return BLE_LL_SCHED_STATE_DONE;
|
||||
}
|
||||
|
||||
static int
|
||||
ble_ll_dtm_rx_create_ctx(uint8_t rf_channel, uint8_t phy_mode)
|
||||
{
|
||||
struct ble_ll_sched_item *sch = &g_ble_ll_dtm_ctx.sch;
|
||||
int rc;
|
||||
|
||||
g_ble_ll_dtm_ctx.phy_mode = phy_mode;
|
||||
g_ble_ll_dtm_ctx.rf_channel = rf_channel;
|
||||
|
||||
STATS_CLEAR(ble_ll_dtm_stats, rx_count);
|
||||
|
||||
ble_npl_event_init(&g_ble_ll_dtm_ctx.evt, ble_ll_dtm_ev_rx_restart_cb,
|
||||
NULL);
|
||||
|
||||
sch->sched_cb = ble_ll_dtm_rx_sched_cb;
|
||||
sch->cb_arg = &g_ble_ll_dtm_ctx;
|
||||
sch->sched_type = BLE_LL_SCHED_TYPE_DTM;
|
||||
sch->start_time = ble_ll_rfmgmt_enable_now();
|
||||
|
||||
rc = ble_ll_sched_dtm(sch);
|
||||
BLE_LL_ASSERT(rc == 0);
|
||||
|
||||
ble_phy_enable_dtm();
|
||||
|
||||
g_ble_ll_dtm_ctx.active = 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
ble_ll_dtm_ctx_free(struct dtm_ctx * ctx)
|
||||
{
|
||||
os_sr_t sr;
|
||||
|
||||
OS_ENTER_CRITICAL(sr);
|
||||
if (!ctx->active) {
|
||||
OS_EXIT_CRITICAL(sr);
|
||||
return;
|
||||
}
|
||||
|
||||
ble_ll_sched_rmv_elem(&ctx->sch);
|
||||
ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &g_ble_ll_dtm_ctx.evt);
|
||||
|
||||
ble_phy_disable();
|
||||
ble_phy_disable_dtm();
|
||||
ble_ll_state_set(BLE_LL_STATE_STANDBY);
|
||||
ble_ll_rfmgmt_release();
|
||||
|
||||
os_mbuf_free_chain(ctx->om);
|
||||
memset(ctx, 0, sizeof(*ctx));
|
||||
OS_EXIT_CRITICAL(sr);
|
||||
}
|
||||
|
||||
static int
|
||||
ble_ll_dtm_tx_test(uint8_t tx_chan, uint8_t len, uint8_t packet_payload,
|
||||
uint8_t hci_phy, uint16_t interval, uint16_t pkt_count)
|
||||
{
|
||||
uint8_t phy_mode;
|
||||
|
||||
if (g_ble_ll_dtm_ctx.active) {
|
||||
return BLE_ERR_CTLR_BUSY;
|
||||
}
|
||||
|
||||
switch (hci_phy) {
|
||||
case BLE_HCI_LE_PHY_1M:
|
||||
phy_mode = BLE_PHY_MODE_1M;
|
||||
break;
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY)
|
||||
case BLE_HCI_LE_PHY_2M:
|
||||
phy_mode = BLE_PHY_MODE_2M;
|
||||
break;
|
||||
#endif
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
|
||||
case BLE_HCI_LE_PHY_CODED_S8:
|
||||
phy_mode = BLE_PHY_MODE_CODED_125KBPS;
|
||||
break;
|
||||
case BLE_HCI_LE_PHY_CODED_S2:
|
||||
phy_mode = BLE_PHY_MODE_CODED_500KBPS;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
if (tx_chan > 0x27 || packet_payload > 0x07) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
if (ble_ll_dtm_tx_create_ctx(packet_payload, len, tx_chan, phy_mode,
|
||||
interval, pkt_count)) {
|
||||
return BLE_ERR_UNSPECIFIED;
|
||||
}
|
||||
|
||||
return BLE_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_DTM_EXTENSIONS)
|
||||
static int
|
||||
ble_ll_hci_dtm_tx_test_ext(const uint8_t *cmdbuf)
|
||||
{
|
||||
const struct ble_hci_le_tx_test_ext_cp *cmd = (const void *) cmdbuf;
|
||||
|
||||
return ble_ll_dtm_tx_test(cmd->tx_chan, cmd->test_data_len, cmd->payload,
|
||||
BLE_HCI_LE_PHY_1M, le16toh(cmd->interval),
|
||||
le16toh(cmd->pkt_count));
|
||||
}
|
||||
|
||||
static int
|
||||
ble_ll_hci_dtm_tx_test_v2_ext(const uint8_t *cmdbuf)
|
||||
{
|
||||
const struct ble_hci_le_tx_test_v2_ext_cp *cmd = (const void *) cmdbuf;
|
||||
|
||||
return ble_ll_dtm_tx_test(cmd->tx_chan, cmd->test_data_len, cmd->payload,
|
||||
cmd->phy, le16toh(cmd->interval),
|
||||
le16toh(cmd->pkt_count));
|
||||
}
|
||||
#endif
|
||||
|
||||
int
|
||||
ble_ll_hci_dtm_tx_test(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
const struct ble_hci_le_tx_test_cp *cmd = (const void *) cmdbuf;
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_DTM_EXTENSIONS)
|
||||
if (len == sizeof(struct ble_hci_le_tx_test_ext_cp)) {
|
||||
return ble_ll_hci_dtm_tx_test_ext(cmdbuf);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (len != sizeof(*cmd)) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
return ble_ll_dtm_tx_test(cmd->tx_chan, cmd->test_data_len, cmd->payload,
|
||||
BLE_HCI_LE_PHY_1M, 0, 0);
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_hci_dtm_tx_test_v2(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
const struct ble_hci_le_tx_test_v2_cp *cmd = (const void *) cmdbuf;
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_DTM_EXTENSIONS)
|
||||
if (len == sizeof(struct ble_hci_le_tx_test_v2_ext_cp)) {
|
||||
return ble_ll_hci_dtm_tx_test_v2_ext(cmdbuf);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (len != sizeof(*cmd)) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
return ble_ll_dtm_tx_test(cmd->tx_chan, cmd->test_data_len, cmd->payload,
|
||||
cmd->phy, 0, 0);
|
||||
}
|
||||
|
||||
static int
|
||||
ble_ll_dtm_rx_test(uint8_t rx_chan, uint8_t hci_phy)
|
||||
{
|
||||
uint8_t phy_mode;
|
||||
|
||||
if (g_ble_ll_dtm_ctx.active) {
|
||||
return BLE_ERR_CTLR_BUSY;
|
||||
}
|
||||
|
||||
switch (hci_phy) {
|
||||
case BLE_HCI_LE_PHY_1M:
|
||||
phy_mode = BLE_PHY_MODE_1M;
|
||||
break;
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_2M_PHY)
|
||||
case BLE_HCI_LE_PHY_2M:
|
||||
phy_mode = BLE_PHY_MODE_2M;
|
||||
break;
|
||||
#endif
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CODED_PHY)
|
||||
case BLE_HCI_LE_PHY_CODED:
|
||||
phy_mode = BLE_PHY_MODE_CODED_500KBPS;
|
||||
break;
|
||||
#endif
|
||||
default:
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
if (rx_chan > 0x27) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
if (ble_ll_dtm_rx_create_ctx(rx_chan, phy_mode)) {
|
||||
return BLE_ERR_UNSPECIFIED;
|
||||
}
|
||||
|
||||
return BLE_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
int ble_ll_hci_dtm_rx_test(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
const struct ble_hci_le_rx_test_cp *cmd = (const void *) cmdbuf;
|
||||
|
||||
if (len != sizeof(*cmd)) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
return ble_ll_dtm_rx_test(cmd->rx_chan, BLE_HCI_LE_PHY_1M);
|
||||
}
|
||||
|
||||
int ble_ll_hci_dtm_rx_test_v2(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
const struct ble_hci_le_rx_test_v2_cp *cmd = (const void *) cmdbuf;
|
||||
|
||||
if (len != sizeof(*cmd)) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
/* TODO ignoring modulation index */
|
||||
|
||||
return ble_ll_dtm_rx_test(cmd->rx_chan, cmd->phy);
|
||||
}
|
||||
|
||||
int ble_ll_dtm_end_test(uint8_t *rsp, uint8_t *rsplen)
|
||||
{
|
||||
put_le16(rsp, g_ble_ll_dtm_ctx. num_of_packets);
|
||||
*rsplen = 2;
|
||||
|
||||
ble_ll_dtm_ctx_free(&g_ble_ll_dtm_ctx);
|
||||
return BLE_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
int ble_ll_dtm_rx_isr_start(struct ble_mbuf_hdr *rxhdr, uint32_t aa)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
ble_ll_dtm_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr)
|
||||
{
|
||||
if (BLE_MBUF_HDR_CRC_OK(hdr)) {
|
||||
/* XXX Compare data. */
|
||||
g_ble_ll_dtm_ctx.num_of_packets++;
|
||||
STATS_INC(ble_ll_dtm_stats, rx_count);
|
||||
}
|
||||
|
||||
if (ble_ll_dtm_rx_start() != 0) {
|
||||
ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &g_ble_ll_dtm_ctx.evt);
|
||||
STATS_INC(ble_ll_dtm_stats, rx_failed);
|
||||
}
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_dtm_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr)
|
||||
{
|
||||
struct os_mbuf *rxpdu;
|
||||
|
||||
if (!g_ble_ll_dtm_ctx.active) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
rxpdu = ble_ll_rxpdu_alloc(rxbuf[1] + BLE_LL_PDU_HDR_LEN);
|
||||
|
||||
/* Copy the received pdu and hand it up */
|
||||
if (rxpdu) {
|
||||
ble_phy_rxpdu_copy(rxbuf, rxpdu);
|
||||
ble_ll_rx_pdu_in(rxpdu);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
ble_ll_dtm_wfr_timer_exp(void)
|
||||
{
|
||||
/* Should not be needed */
|
||||
BLE_LL_ASSERT(0);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
ble_ll_dtm_reset(void)
|
||||
{
|
||||
ble_ll_dtm_ctx_free(&g_ble_ll_dtm_ctx);
|
||||
}
|
||||
|
||||
void
|
||||
ble_ll_dtm_init(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
rc = stats_init_and_reg(STATS_HDR(ble_ll_dtm_stats),
|
||||
STATS_SIZE_INIT_PARMS(ble_ll_dtm_stats, STATS_SIZE_32),
|
||||
STATS_NAME_INIT_PARMS(ble_ll_dtm_stats),
|
||||
"ble_ll_dtm");
|
||||
SYSINIT_PANIC_ASSERT(rc == 0);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef H_BLE_LL_TEST_PRIV_
|
||||
#define H_BLE_LL_TEST_PRIV_
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "nimble/ble.h"
|
||||
|
||||
int ble_ll_hci_dtm_tx_test(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_hci_dtm_tx_test_v2(const uint8_t *cmdbuf, uint8_t len);
|
||||
|
||||
int ble_ll_hci_dtm_rx_test(const uint8_t *cmdbuf, uint8_t len);
|
||||
int ble_ll_hci_dtm_rx_test_v2(const uint8_t *cmdbuf, uint8_t len);
|
||||
|
||||
int ble_ll_dtm_end_test(uint8_t *rsp, uint8_t *rsplen);
|
||||
|
||||
int ble_ll_dtm_rx_isr_start(struct ble_mbuf_hdr *rxhdr, uint32_t aa);
|
||||
int ble_ll_dtm_rx_isr_end(uint8_t *rxbuf, struct ble_mbuf_hdr *rxhdr);
|
||||
void ble_ll_dtm_rx_pkt_in(struct os_mbuf *rxpdu, struct ble_mbuf_hdr *hdr);
|
||||
void ble_ll_dtm_wfr_timer_exp(void);
|
||||
void ble_ll_dtm_reset(void);
|
||||
#endif
|
||||
1519
lib/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_hci.c
Normal file
1519
lib/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_hci.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,526 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
#ifndef ESP_PLATFORM
|
||||
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "nimble/porting/nimble/include/syscfg/syscfg.h"
|
||||
#include "nimble/nimble/include/nimble/ble.h"
|
||||
#include "nimble/nimble/include/nimble/hci_common.h"
|
||||
#include "nimble/nimble/include/nimble/ble_hci_trans.h"
|
||||
#include "../include/controller/ble_ll.h"
|
||||
#include "../include/controller/ble_ll_hci.h"
|
||||
#include "../include/controller/ble_ll_ctrl.h"
|
||||
#include "ble_ll_conn_priv.h"
|
||||
|
||||
#if (BLETEST_CONCURRENT_CONN_TEST == 1)
|
||||
extern void bletest_ltk_req_reply(uint16_t handle);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Send a data length change event for a connection to the host.
|
||||
*
|
||||
* @param connsm Pointer to connection state machine
|
||||
*/
|
||||
void
|
||||
ble_ll_hci_ev_datalen_chg(struct ble_ll_conn_sm *connsm)
|
||||
{
|
||||
struct ble_hci_ev_le_subev_data_len_chg *ev;
|
||||
struct ble_hci_ev *hci_ev;
|
||||
|
||||
if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_DATA_LEN_CHG)) {
|
||||
hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
|
||||
if (hci_ev) {
|
||||
hci_ev->opcode = BLE_HCI_EVCODE_LE_META;
|
||||
hci_ev->length = sizeof(*ev);
|
||||
ev = (void *) hci_ev->data;
|
||||
|
||||
ev->subev_code = BLE_HCI_LE_SUBEV_DATA_LEN_CHG;
|
||||
ev->conn_handle = htole16(connsm->conn_handle);
|
||||
|
||||
ev->max_tx_octets = htole16(connsm->eff_max_tx_octets);
|
||||
ev->max_tx_time = htole16(connsm->eff_max_tx_time);
|
||||
ev->max_rx_octets = htole16(connsm->eff_max_rx_octets);
|
||||
ev->max_rx_time = htole16(connsm->eff_max_rx_time);
|
||||
|
||||
ble_ll_hci_event_send(hci_ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a connection parameter request event for a connection to the host.
|
||||
*
|
||||
* @param connsm Pointer to connection state machine
|
||||
*/
|
||||
void
|
||||
ble_ll_hci_ev_rem_conn_parm_req(struct ble_ll_conn_sm *connsm,
|
||||
struct ble_ll_conn_params *cp)
|
||||
{
|
||||
struct ble_hci_ev_le_subev_rem_conn_param_req *ev;
|
||||
struct ble_hci_ev *hci_ev;
|
||||
|
||||
if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_REM_CONN_PARM_REQ)) {
|
||||
hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
|
||||
if (hci_ev) {
|
||||
hci_ev->opcode = BLE_HCI_EVCODE_LE_META;
|
||||
hci_ev->length = sizeof(*ev);
|
||||
ev = (void *) hci_ev->data;
|
||||
|
||||
ev->subev_code = BLE_HCI_LE_SUBEV_REM_CONN_PARM_REQ;
|
||||
ev->conn_handle = htole16(connsm->conn_handle);
|
||||
ev->min_interval = htole16(cp->interval_min);
|
||||
ev->max_interval = htole16(cp->interval_max);
|
||||
ev->latency = htole16(cp->latency);
|
||||
ev->timeout = htole16(cp->timeout);
|
||||
|
||||
ble_ll_hci_event_send(hci_ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a connection update event.
|
||||
*
|
||||
* @param connsm Pointer to connection state machine
|
||||
* @param status The error code.
|
||||
*/
|
||||
void
|
||||
ble_ll_hci_ev_conn_update(struct ble_ll_conn_sm *connsm, uint8_t status)
|
||||
{
|
||||
struct ble_hci_ev_le_subev_conn_upd_complete *ev;
|
||||
struct ble_hci_ev *hci_ev;
|
||||
|
||||
if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_CONN_UPD_COMPLETE)) {
|
||||
hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
|
||||
if (hci_ev) {
|
||||
hci_ev->opcode = BLE_HCI_EVCODE_LE_META;
|
||||
hci_ev->length = sizeof(*ev);
|
||||
ev = (void *) hci_ev->data;
|
||||
|
||||
ev->subev_code = BLE_HCI_LE_SUBEV_CONN_UPD_COMPLETE;
|
||||
ev->status = status;
|
||||
ev->conn_handle = htole16(connsm->conn_handle);
|
||||
ev->conn_itvl = htole16(connsm->conn_itvl);
|
||||
ev->conn_latency = htole16(connsm->slave_latency);
|
||||
ev->supervision_timeout = htole16(connsm->supervision_tmo);
|
||||
|
||||
ble_ll_hci_event_send(hci_ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
|
||||
void
|
||||
ble_ll_hci_ev_encrypt_chg(struct ble_ll_conn_sm *connsm, uint8_t status)
|
||||
{
|
||||
struct ble_hci_ev_enc_key_refresh *ev_key_refresh;
|
||||
struct ble_hci_ev_enrypt_chg *ev_enc_chf;
|
||||
struct ble_hci_ev *hci_ev;
|
||||
|
||||
if (CONN_F_ENC_CHANGE_SENT(connsm) == 0) {
|
||||
if (ble_ll_hci_is_event_enabled(BLE_HCI_EVCODE_ENCRYPT_CHG)) {
|
||||
hci_ev = (void *)ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
|
||||
if (hci_ev) {
|
||||
hci_ev->opcode = BLE_HCI_EVCODE_ENCRYPT_CHG;
|
||||
hci_ev->length = sizeof(*ev_enc_chf);
|
||||
ev_enc_chf = (void *) hci_ev->data;
|
||||
|
||||
ev_enc_chf->status = status;
|
||||
ev_enc_chf->connection_handle = htole16(connsm->conn_handle);
|
||||
ev_enc_chf->enabled = (status == BLE_ERR_SUCCESS) ? 0x01 : 0x00;
|
||||
|
||||
ble_ll_hci_event_send(hci_ev);
|
||||
}
|
||||
}
|
||||
|
||||
CONN_F_ENC_CHANGE_SENT(connsm) = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
if (ble_ll_hci_is_event_enabled(BLE_HCI_EVCODE_ENC_KEY_REFRESH)) {
|
||||
hci_ev = (void *)ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
|
||||
if (hci_ev) {
|
||||
hci_ev->opcode = BLE_HCI_EVCODE_ENC_KEY_REFRESH;
|
||||
hci_ev->length = sizeof(*ev_key_refresh);
|
||||
ev_key_refresh = (void *) hci_ev->data;
|
||||
|
||||
ev_key_refresh->status = status;
|
||||
ev_key_refresh->conn_handle = htole16(connsm->conn_handle);
|
||||
|
||||
ble_ll_hci_event_send(hci_ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a long term key request event for a connection to the host.
|
||||
*
|
||||
* @param connsm Pointer to connection state machine
|
||||
*/
|
||||
int
|
||||
ble_ll_hci_ev_ltk_req(struct ble_ll_conn_sm *connsm)
|
||||
{
|
||||
struct ble_hci_ev_le_subev_lt_key_req *ev;
|
||||
struct ble_hci_ev *hci_ev;
|
||||
int rc;
|
||||
|
||||
if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_LT_KEY_REQ)) {
|
||||
hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
|
||||
if (hci_ev) {
|
||||
hci_ev->opcode = BLE_HCI_EVCODE_LE_META;
|
||||
hci_ev->length = sizeof(*ev);
|
||||
ev = (void *) hci_ev->data;
|
||||
|
||||
ev->subev_code = BLE_HCI_LE_SUBEV_LT_KEY_REQ;
|
||||
ev->conn_handle = htole16(connsm->conn_handle);
|
||||
ev->rand = htole64(connsm->enc_data.host_rand_num);
|
||||
ev->div = htole16(connsm->enc_data.enc_div);
|
||||
|
||||
ble_ll_hci_event_send(hci_ev);
|
||||
}
|
||||
rc = 0;
|
||||
} else {
|
||||
rc = -1;
|
||||
}
|
||||
|
||||
#if (BLETEST_CONCURRENT_CONN_TEST == 1)
|
||||
if (rc == 0) {
|
||||
bletest_ltk_req_reply(connsm->conn_handle);
|
||||
}
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
ble_ll_hci_ev_rd_rem_used_feat(struct ble_ll_conn_sm *connsm, uint8_t status)
|
||||
{
|
||||
struct ble_hci_ev_le_subev_rd_rem_used_feat *ev;
|
||||
struct ble_hci_ev *hci_ev;
|
||||
|
||||
if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_RD_REM_USED_FEAT)) {
|
||||
hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
|
||||
if (hci_ev) {
|
||||
hci_ev->opcode = BLE_HCI_EVCODE_LE_META;
|
||||
hci_ev->length = sizeof(*ev);
|
||||
ev = (void *) hci_ev->data;
|
||||
|
||||
ev->subev_code = BLE_HCI_LE_SUBEV_RD_REM_USED_FEAT;
|
||||
ev->status = status;
|
||||
ev->conn_handle = htole16(connsm->conn_handle);
|
||||
ev->features[0] = connsm->conn_features;
|
||||
memcpy(ev->features + 1, connsm->remote_features, 7);
|
||||
|
||||
ble_ll_hci_event_send(hci_ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ble_ll_hci_ev_rd_rem_ver(struct ble_ll_conn_sm *connsm, uint8_t status)
|
||||
{
|
||||
struct ble_hci_ev_rd_rem_ver_info_cmp *ev;
|
||||
struct ble_hci_ev *hci_ev;
|
||||
|
||||
if (ble_ll_hci_is_event_enabled(BLE_HCI_EVCODE_RD_REM_VER_INFO_CMP)) {
|
||||
hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
|
||||
if (hci_ev) {
|
||||
hci_ev->opcode = BLE_HCI_EVCODE_RD_REM_VER_INFO_CMP;
|
||||
hci_ev->length = sizeof(*ev);
|
||||
ev = (void *) hci_ev->data;
|
||||
|
||||
ev->status = status;
|
||||
ev->conn_handle = htole16(connsm->conn_handle);
|
||||
ev->version = connsm->vers_nr;
|
||||
ev->manufacturer = htole16(connsm->comp_id);
|
||||
ev->subversion = htole16(connsm->sub_vers_nr);
|
||||
|
||||
ble_ll_hci_event_send(hci_ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a HW error to the host.
|
||||
*
|
||||
* @param hw_err
|
||||
*
|
||||
* @return int 0: event masked or event sent, -1 otherwise
|
||||
*/
|
||||
int
|
||||
ble_ll_hci_ev_hw_err(uint8_t hw_err)
|
||||
{
|
||||
struct ble_hci_ev_hw_error *ev;
|
||||
struct ble_hci_ev *hci_ev;
|
||||
int rc;
|
||||
|
||||
rc = 0;
|
||||
if (ble_ll_hci_is_event_enabled(BLE_HCI_EVCODE_HW_ERROR)) {
|
||||
hci_ev = (void *)ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
|
||||
if (hci_ev) {
|
||||
hci_ev->opcode = BLE_HCI_EVCODE_HW_ERROR;
|
||||
hci_ev->length = sizeof(*ev);
|
||||
ev = (void *) hci_ev->data;
|
||||
|
||||
ev->hw_code = hw_err;
|
||||
|
||||
ble_ll_hci_event_send(hci_ev);
|
||||
} else {
|
||||
rc = -1;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
void
|
||||
ble_ll_hci_ev_databuf_overflow(void)
|
||||
{
|
||||
struct ble_hci_ev_data_buf_overflow *ev;
|
||||
struct ble_hci_ev *hci_ev;
|
||||
|
||||
if (ble_ll_hci_is_event_enabled(BLE_HCI_EVCODE_DATA_BUF_OVERFLOW)) {
|
||||
hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
|
||||
if (hci_ev) {
|
||||
hci_ev->opcode = BLE_HCI_EVCODE_DATA_BUF_OVERFLOW;
|
||||
hci_ev->length = sizeof(*ev);
|
||||
ev = (void *) hci_ev->data;
|
||||
|
||||
ev->link_type = BLE_HCI_EVENT_ACL_BUF_OVERFLOW;
|
||||
|
||||
ble_ll_hci_event_send(hci_ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a LE Channel Selection Algorithm event.
|
||||
*
|
||||
* @param connsm Pointer to connection state machine
|
||||
*/
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2)
|
||||
void
|
||||
ble_ll_hci_ev_le_csa(struct ble_ll_conn_sm *connsm)
|
||||
{
|
||||
struct ble_hci_ev_le_subev_chan_sel_alg *ev;
|
||||
struct ble_hci_ev *hci_ev;
|
||||
|
||||
if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_CHAN_SEL_ALG)) {
|
||||
hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
|
||||
if (hci_ev) {
|
||||
hci_ev->opcode = BLE_HCI_EVCODE_LE_META;
|
||||
hci_ev->length = sizeof(*ev);
|
||||
ev = (void *) hci_ev->data;
|
||||
|
||||
ev->subev_code = BLE_HCI_LE_SUBEV_CHAN_SEL_ALG;
|
||||
ev->conn_handle = htole16(connsm->conn_handle);
|
||||
ev->csa = connsm->csmflags.cfbit.csa2_supp ? 0x01 : 0x00;
|
||||
|
||||
ble_ll_hci_event_send(hci_ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Sends the LE Scan Request Received event
|
||||
*
|
||||
*/
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
|
||||
void
|
||||
ble_ll_hci_ev_send_scan_req_recv(uint8_t adv_handle, const uint8_t *peer,
|
||||
uint8_t peer_addr_type)
|
||||
{
|
||||
struct ble_hci_ev_le_subev_scan_req_rcvd *ev;
|
||||
struct ble_hci_ev *hci_ev;
|
||||
|
||||
if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_SCAN_REQ_RCVD)) {
|
||||
hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
|
||||
if (hci_ev) {
|
||||
hci_ev->opcode = BLE_HCI_EVCODE_LE_META;
|
||||
hci_ev->length = sizeof(*ev);
|
||||
ev = (void *) hci_ev->data;
|
||||
|
||||
ev->subev_code = BLE_HCI_LE_SUBEV_SCAN_REQ_RCVD;
|
||||
ev->adv_handle = adv_handle;
|
||||
ev->peer_addr_type = peer_addr_type;
|
||||
memcpy(ev->peer_addr, peer, BLE_DEV_ADDR_LEN);
|
||||
|
||||
ble_ll_hci_event_send(hci_ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Sends the LE Scan Timeout Event
|
||||
*
|
||||
*/
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
|
||||
void
|
||||
ble_ll_hci_ev_send_scan_timeout(void)
|
||||
{
|
||||
struct ble_hci_ev_le_subev_scan_timeout *ev;
|
||||
struct ble_hci_ev *hci_ev;
|
||||
|
||||
if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_SCAN_TIMEOUT)) {
|
||||
hci_ev = (void *)ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
|
||||
if (hci_ev) {
|
||||
hci_ev->opcode = BLE_HCI_EVCODE_LE_META;
|
||||
hci_ev->length = sizeof(*ev);
|
||||
ev = (void *) hci_ev->data;
|
||||
|
||||
ev->subev_code = BLE_HCI_LE_SUBEV_SCAN_TIMEOUT;
|
||||
|
||||
ble_ll_hci_event_send(hci_ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Sends the LE Advertising Set Terminated event
|
||||
*
|
||||
*/
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
|
||||
void
|
||||
ble_ll_hci_ev_send_adv_set_terminated(uint8_t status, uint8_t adv_handle,
|
||||
uint16_t conn_handle, uint8_t events)
|
||||
{
|
||||
struct ble_hci_ev_le_subev_adv_set_terminated *ev;
|
||||
struct ble_hci_ev *hci_ev;
|
||||
|
||||
if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_ADV_SET_TERMINATED)) {
|
||||
hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
|
||||
if (hci_ev) {
|
||||
hci_ev->opcode = BLE_HCI_EVCODE_LE_META;
|
||||
hci_ev->length = sizeof(*ev);
|
||||
ev = (void *) hci_ev->data;
|
||||
|
||||
ev->subev_code = BLE_HCI_LE_SUBEV_ADV_SET_TERMINATED;
|
||||
ev->status = status;
|
||||
ev->adv_handle = adv_handle;
|
||||
ev->conn_handle = htole16(conn_handle);
|
||||
ev->num_events = events;
|
||||
|
||||
ble_ll_hci_event_send(hci_ev);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Send a PHY update complete event
|
||||
*
|
||||
* @param connsm Pointer to connection state machine
|
||||
* @param status error status of event
|
||||
*/
|
||||
#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
|
||||
int
|
||||
ble_ll_hci_ev_phy_update(struct ble_ll_conn_sm *connsm, uint8_t status)
|
||||
{
|
||||
struct ble_hci_ev_le_subev_phy_update_complete *ev;
|
||||
struct ble_hci_ev *hci_ev;
|
||||
int rc;
|
||||
|
||||
rc = 0;
|
||||
if (ble_ll_hci_is_le_event_enabled(BLE_HCI_LE_SUBEV_PHY_UPDATE_COMPLETE)) {
|
||||
hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
|
||||
if (hci_ev) {
|
||||
hci_ev->opcode = BLE_HCI_EVCODE_LE_META;
|
||||
hci_ev->length = sizeof(*ev);
|
||||
ev = (void *) hci_ev->data;
|
||||
|
||||
ev->subev_code = BLE_HCI_LE_SUBEV_PHY_UPDATE_COMPLETE;
|
||||
ev->status = status;
|
||||
ev->conn_handle = htole16(connsm->conn_handle);
|
||||
ev->tx_phy = connsm->phy_data.cur_tx_phy;
|
||||
ev->rx_phy = connsm->phy_data.cur_rx_phy;
|
||||
|
||||
ble_ll_hci_event_send(hci_ev);
|
||||
} else {
|
||||
rc = BLE_ERR_MEM_CAPACITY;
|
||||
}
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
#endif
|
||||
|
||||
void
|
||||
ble_ll_hci_ev_send_vendor_err(const char *file, uint32_t line)
|
||||
{
|
||||
struct ble_hci_ev_vendor_debug *ev;
|
||||
struct ble_hci_ev *hci_ev;
|
||||
unsigned int str_len;
|
||||
bool skip = true;
|
||||
uint8_t digit;
|
||||
int max_len;
|
||||
int i;
|
||||
|
||||
/* 6 is for line number ":00000" , we assume files have no more than 64k of
|
||||
* lines
|
||||
*/
|
||||
max_len = BLE_HCI_MAX_DATA_LEN - sizeof(*ev) - 6;
|
||||
|
||||
hci_ev = (void *) ble_hci_trans_buf_alloc(BLE_HCI_TRANS_BUF_EVT_HI);
|
||||
if (hci_ev) {
|
||||
hci_ev->opcode = BLE_HCI_EVCODE_VENDOR_DEBUG;
|
||||
hci_ev->length = sizeof(*ev);
|
||||
ev = (void *) hci_ev->data;
|
||||
|
||||
/* Debug id for future use */
|
||||
ev->id = 0x00;
|
||||
|
||||
/* snprintf would be nicer but this is heavy on flash
|
||||
* len = snprintf((char *) ev->data, max_len, "%s:%u", file, line);
|
||||
* if (len < 0) {
|
||||
* len = 0;
|
||||
* } else if (len > max_len) {
|
||||
* len = max_len;
|
||||
* }
|
||||
*
|
||||
* hci_ev->length += len;
|
||||
*/
|
||||
str_len = strlen(file);
|
||||
if (str_len > max_len) {
|
||||
str_len = max_len;
|
||||
}
|
||||
|
||||
memcpy(ev->data, file, str_len);
|
||||
ev->data[str_len++] = ':';
|
||||
|
||||
for (i = 100000; i >= 10; i /= 10) {
|
||||
digit = (line % i) / (i/10);
|
||||
|
||||
if (!digit && skip) {
|
||||
continue;
|
||||
}
|
||||
|
||||
skip = false;
|
||||
ev->data[str_len++] = '0' + digit;
|
||||
}
|
||||
|
||||
hci_ev->length += str_len;
|
||||
|
||||
ble_ll_hci_event_send(hci_ev);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef H_BLE_LL_PRIV_
|
||||
#define H_BLE_LL_PRIV_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef MYNEWT
|
||||
|
||||
#include "syscfg/syscfg.h"
|
||||
#include "hal/hal_gpio.h"
|
||||
|
||||
#define BLE_LL_DEBUG_GPIO_INIT(_name) \
|
||||
if (MYNEWT_VAL(BLE_LL_DEBUG_GPIO_ ## _name) >= 0) { \
|
||||
hal_gpio_init_out(MYNEWT_VAL(BLE_LL_DEBUG_GPIO_ ## _name), 0); \
|
||||
}
|
||||
|
||||
#define BLE_LL_DEBUG_GPIO(_name, _val) \
|
||||
if (MYNEWT_VAL(BLE_LL_DEBUG_GPIO_ ## _name) >= 0) { \
|
||||
hal_gpio_write(MYNEWT_VAL(BLE_LL_DEBUG_GPIO_ ## _name), !!(_val)); \
|
||||
}
|
||||
|
||||
#else
|
||||
#define BLE_LL_DEBUG_GPIO_INIT(_name) (void)(0)
|
||||
#define BLE_LL_DEBUG_GPIO(_name, _val) (void)(0)
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* H_BLE_LL_PRIV_ */
|
||||
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
#ifndef ESP_PLATFORM
|
||||
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "nimble/porting/nimble/include/syscfg/syscfg.h"
|
||||
#include "nimble/porting/nimble/include/os/os.h"
|
||||
#include "nimble/nimble/include/nimble/ble.h"
|
||||
#include "nimble/nimble/include/nimble/nimble_opt.h"
|
||||
#include "../include/controller/ble_hw.h"
|
||||
#include "../include/controller/ble_ll.h"
|
||||
#if MYNEWT_VAL(TRNG)
|
||||
#include "trng/trng.h"
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(TRNG)
|
||||
static struct trng_dev *g_trng;
|
||||
#else
|
||||
/* This is a simple circular buffer for holding N samples of random data */
|
||||
struct ble_ll_rnum_data
|
||||
{
|
||||
uint8_t *rnd_in;
|
||||
uint8_t *rnd_out;
|
||||
volatile uint8_t rnd_size;
|
||||
};
|
||||
|
||||
struct ble_ll_rnum_data g_ble_ll_rnum_data;
|
||||
uint8_t g_ble_ll_rnum_buf[MYNEWT_VAL(BLE_LL_RNG_BUFSIZE)];
|
||||
|
||||
#define IS_RNUM_BUF_END(x) \
|
||||
(x == &g_ble_ll_rnum_buf[MYNEWT_VAL(BLE_LL_RNG_BUFSIZE) - 1])
|
||||
|
||||
void
|
||||
ble_ll_rand_sample(uint8_t rnum)
|
||||
{
|
||||
os_sr_t sr;
|
||||
|
||||
OS_ENTER_CRITICAL(sr);
|
||||
if (g_ble_ll_rnum_data.rnd_size < MYNEWT_VAL(BLE_LL_RNG_BUFSIZE)) {
|
||||
++g_ble_ll_rnum_data.rnd_size;
|
||||
g_ble_ll_rnum_data.rnd_in[0] = rnum;
|
||||
if (IS_RNUM_BUF_END(g_ble_ll_rnum_data.rnd_in)) {
|
||||
g_ble_ll_rnum_data.rnd_in = g_ble_ll_rnum_buf;
|
||||
} else {
|
||||
++g_ble_ll_rnum_data.rnd_in;
|
||||
}
|
||||
} else {
|
||||
/* Stop generating random numbers as we are full */
|
||||
ble_hw_rng_stop();
|
||||
}
|
||||
OS_EXIT_CRITICAL(sr);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Get 'len' bytes of random data */
|
||||
int
|
||||
ble_ll_rand_data_get(uint8_t *buf, uint8_t len)
|
||||
{
|
||||
#if MYNEWT_VAL(TRNG)
|
||||
size_t num;
|
||||
|
||||
while (len) {
|
||||
num = trng_read(g_trng, buf, len);
|
||||
buf += num;
|
||||
len -= num;
|
||||
}
|
||||
#else
|
||||
uint8_t rnums;
|
||||
os_sr_t sr;
|
||||
|
||||
while (len != 0) {
|
||||
OS_ENTER_CRITICAL(sr);
|
||||
rnums = g_ble_ll_rnum_data.rnd_size;
|
||||
if (rnums > len) {
|
||||
rnums = len;
|
||||
}
|
||||
len -= rnums;
|
||||
g_ble_ll_rnum_data.rnd_size -= rnums;
|
||||
while (rnums) {
|
||||
buf[0] = g_ble_ll_rnum_data.rnd_out[0];
|
||||
if (IS_RNUM_BUF_END(g_ble_ll_rnum_data.rnd_out)) {
|
||||
g_ble_ll_rnum_data.rnd_out = g_ble_ll_rnum_buf;
|
||||
} else {
|
||||
++g_ble_ll_rnum_data.rnd_out;
|
||||
}
|
||||
++buf;
|
||||
--rnums;
|
||||
}
|
||||
OS_EXIT_CRITICAL(sr);
|
||||
|
||||
/* Make sure rng is started! */
|
||||
ble_hw_rng_start();
|
||||
|
||||
/* Wait till bytes are in buffer. */
|
||||
if (len) {
|
||||
while ((g_ble_ll_rnum_data.rnd_size < len) &&
|
||||
(g_ble_ll_rnum_data.rnd_size < MYNEWT_VAL(BLE_LL_RNG_BUFSIZE))) {
|
||||
/* Spin here */
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
return BLE_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to obtain a "prand" as defined in core V4.2 Vol 6 Part B 1.3.2.2
|
||||
*
|
||||
* @param prand
|
||||
*/
|
||||
void
|
||||
ble_ll_rand_prand_get(uint8_t *prand)
|
||||
{
|
||||
uint16_t sum;
|
||||
|
||||
while (1) {
|
||||
/* Get 24 bits of random data */
|
||||
ble_ll_rand_data_get(prand, 3);
|
||||
|
||||
/* Prand cannot be all zeros or 1's. */
|
||||
sum = prand[0] + prand[1] + prand[2];
|
||||
if ((sum != 0) && (sum != (3 * 0xff))) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Upper two bits must be 01 */
|
||||
prand[2] &= ~0xc0;
|
||||
prand[2] |= 0x40;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the generation of random numbers
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int
|
||||
ble_ll_rand_start(void)
|
||||
{
|
||||
#if MYNEWT_VAL(TRNG)
|
||||
/* Nothing to do - this is handled by driver */
|
||||
#else
|
||||
/* Start the generation of numbers if we are not full */
|
||||
if (g_ble_ll_rnum_data.rnd_size < MYNEWT_VAL(BLE_LL_RNG_BUFSIZE)) {
|
||||
ble_hw_rng_start();
|
||||
}
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize LL random number generation. Should be called only once on
|
||||
* initialization.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int
|
||||
ble_ll_rand_init(void)
|
||||
{
|
||||
#if MYNEWT_VAL(TRNG)
|
||||
g_trng = (struct trng_dev *) os_dev_open("trng", OS_TIMEOUT_NEVER, NULL);
|
||||
#else
|
||||
g_ble_ll_rnum_data.rnd_in = g_ble_ll_rnum_buf;
|
||||
g_ble_ll_rnum_data.rnd_out = g_ble_ll_rnum_buf;
|
||||
ble_hw_rng_init(ble_ll_rand_sample, 1);
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,755 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
#ifndef ESP_PLATFORM
|
||||
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "nimble/porting/nimble/include/syscfg/syscfg.h"
|
||||
#include "nimble/porting/nimble/include/os/os.h"
|
||||
#include "nimble/nimble/include/nimble/ble.h"
|
||||
#include "nimble/nimble/include/nimble/nimble_opt.h"
|
||||
#include "../include/controller/ble_ll.h"
|
||||
#include "../include/controller/ble_ll_resolv.h"
|
||||
#include "../include/controller/ble_ll_hci.h"
|
||||
#include "../include/controller/ble_ll_scan.h"
|
||||
#include "../include/controller/ble_ll_adv.h"
|
||||
#include "../include/controller/ble_ll_sync.h"
|
||||
#include "../include/controller/ble_hw.h"
|
||||
#include "ble_ll_conn_priv.h"
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
|
||||
struct ble_ll_resolv_data
|
||||
{
|
||||
uint8_t addr_res_enabled;
|
||||
uint8_t rl_size;
|
||||
uint8_t rl_cnt_hw;
|
||||
uint8_t rl_cnt;
|
||||
ble_npl_time_t rpa_tmo;
|
||||
struct ble_npl_callout rpa_timer;
|
||||
};
|
||||
struct ble_ll_resolv_data g_ble_ll_resolv_data;
|
||||
|
||||
__attribute__((aligned(4)))
|
||||
struct ble_ll_resolv_entry g_ble_ll_resolv_list[MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE)];
|
||||
|
||||
static int
|
||||
ble_ll_is_controller_busy(void)
|
||||
{
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV)
|
||||
if (ble_ll_sync_enabled()) {
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
return ble_ll_adv_enabled() || ble_ll_scan_enabled() ||
|
||||
g_ble_ll_conn_create_sm;
|
||||
}
|
||||
/**
|
||||
* Called to determine if a change is allowed to the resolving list at this
|
||||
* time. We are not allowed to modify the resolving list if address translation
|
||||
* is enabled and we are either scanning, advertising, or attempting to create
|
||||
* a connection.
|
||||
*
|
||||
* @return int 0: not allowed. 1: allowed.
|
||||
*/
|
||||
static int
|
||||
ble_ll_resolv_list_chg_allowed(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if (g_ble_ll_resolv_data.addr_res_enabled &&
|
||||
ble_ll_is_controller_busy()) {
|
||||
rc = 0;
|
||||
} else {
|
||||
rc = 1;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Called to generate a resolvable private address in rl structure
|
||||
*
|
||||
* @param rl
|
||||
* @param local
|
||||
*/
|
||||
static void
|
||||
ble_ll_resolv_gen_priv_addr(struct ble_ll_resolv_entry *rl, int local)
|
||||
{
|
||||
uint8_t *irk;
|
||||
uint8_t *prand;
|
||||
struct ble_encryption_block ecb;
|
||||
uint8_t *addr;
|
||||
|
||||
BLE_LL_ASSERT(rl != NULL);
|
||||
|
||||
if (local) {
|
||||
addr = rl->rl_local_rpa;
|
||||
irk = rl->rl_local_irk;
|
||||
} else {
|
||||
addr = rl->rl_peer_rpa;
|
||||
irk = rl->rl_peer_irk;
|
||||
}
|
||||
|
||||
/* Get prand */
|
||||
prand = addr + 3;
|
||||
ble_ll_rand_prand_get(prand);
|
||||
|
||||
/* Calculate hash, hash = ah(local IRK, prand) */
|
||||
memcpy(ecb.key, irk, 16);
|
||||
memset(ecb.plain_text, 0, 13);
|
||||
ecb.plain_text[13] = prand[2];
|
||||
ecb.plain_text[14] = prand[1];
|
||||
ecb.plain_text[15] = prand[0];
|
||||
|
||||
/* Calculate hash */
|
||||
ble_hw_encrypt_block(&ecb);
|
||||
|
||||
addr[0] = ecb.cipher_text[15];
|
||||
addr[1] = ecb.cipher_text[14];
|
||||
addr[2] = ecb.cipher_text[13];
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when the Resolvable private address timer expires. This timer
|
||||
* is used to regenerate local and peers RPA's in the resolving list.
|
||||
*/
|
||||
static void
|
||||
ble_ll_resolv_rpa_timer_cb(struct ble_npl_event *ev)
|
||||
{
|
||||
int i;
|
||||
os_sr_t sr;
|
||||
struct ble_ll_resolv_entry *rl;
|
||||
|
||||
rl = &g_ble_ll_resolv_list[0];
|
||||
for (i = 0; i < g_ble_ll_resolv_data.rl_cnt; ++i) {
|
||||
if (rl->rl_has_local) {
|
||||
OS_ENTER_CRITICAL(sr);
|
||||
ble_ll_resolv_gen_priv_addr(rl, 1);
|
||||
OS_EXIT_CRITICAL(sr);
|
||||
}
|
||||
|
||||
if (rl->rl_has_peer) {
|
||||
OS_ENTER_CRITICAL(sr);
|
||||
ble_ll_resolv_gen_priv_addr(rl, 0);
|
||||
OS_EXIT_CRITICAL(sr);
|
||||
}
|
||||
++rl;
|
||||
}
|
||||
|
||||
ble_npl_callout_reset(&g_ble_ll_resolv_data.rpa_timer,
|
||||
g_ble_ll_resolv_data.rpa_tmo);
|
||||
|
||||
ble_ll_adv_rpa_timeout();
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to determine if the IRK is all zero.
|
||||
*
|
||||
* @param irk
|
||||
*
|
||||
* @return int 0: IRK is zero . 1: IRK has non-zero value.
|
||||
*/
|
||||
static int
|
||||
ble_ll_resolv_irk_nonzero(const uint8_t *irk)
|
||||
{
|
||||
int i;
|
||||
int rc;
|
||||
|
||||
rc = 0;
|
||||
for (i = 0; i < 16; ++i) {
|
||||
if (*irk != 0) {
|
||||
rc = 1;
|
||||
break;
|
||||
}
|
||||
++irk;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the resolving list
|
||||
*
|
||||
* @return int 0: success, BLE error code otherwise
|
||||
*/
|
||||
int
|
||||
ble_ll_resolv_list_clr(void)
|
||||
{
|
||||
/* Check proper state */
|
||||
if (!ble_ll_resolv_list_chg_allowed()) {
|
||||
return BLE_ERR_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
/* Sets total on list to 0. Clears HW resolve list */
|
||||
g_ble_ll_resolv_data.rl_cnt_hw = 0;
|
||||
g_ble_ll_resolv_data.rl_cnt = 0;
|
||||
ble_hw_resolv_list_clear();
|
||||
|
||||
/* stop RPA timer when clearing RL */
|
||||
ble_npl_callout_stop(&g_ble_ll_resolv_data.rpa_timer);
|
||||
|
||||
return BLE_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the size of the resolving list. This is the total number of resolving
|
||||
* list entries allowed by the controller.
|
||||
*
|
||||
* @param rspbuf Pointer to response buffer
|
||||
*
|
||||
* @return int 0: success.
|
||||
*/
|
||||
int
|
||||
ble_ll_resolv_list_read_size(uint8_t *rspbuf, uint8_t *rsplen)
|
||||
{
|
||||
struct ble_hci_le_rd_resolv_list_size_rp *rsp = (void *) rspbuf;
|
||||
|
||||
rsp->size = g_ble_ll_resolv_data.rl_size;
|
||||
|
||||
*rsplen = sizeof(*rsp);
|
||||
return BLE_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to determine if the device is on the resolving list.
|
||||
*
|
||||
* @param addr
|
||||
* @param addr_type Public address (0) or random address (1)
|
||||
*
|
||||
* @return int 0: device is not on resolving list; otherwise the return value
|
||||
* is the 'position' of the device in the resolving list (the index of the
|
||||
* element plus 1).
|
||||
*/
|
||||
static int
|
||||
ble_ll_is_on_resolv_list(const uint8_t *addr, uint8_t addr_type)
|
||||
{
|
||||
int i;
|
||||
struct ble_ll_resolv_entry *rl;
|
||||
|
||||
rl = &g_ble_ll_resolv_list[0];
|
||||
for (i = 0; i < g_ble_ll_resolv_data.rl_cnt; ++i) {
|
||||
if ((rl->rl_addr_type == addr_type) &&
|
||||
(!memcmp(&rl->rl_identity_addr[0], addr, BLE_DEV_ADDR_LEN))) {
|
||||
return i + 1;
|
||||
}
|
||||
++rl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Used to determine if the device is on the resolving list.
|
||||
*
|
||||
* @param addr
|
||||
* @param addr_type Public address (0) or random address (1)
|
||||
*
|
||||
* @return Pointer to resolving list entry or NULL if no entry found.
|
||||
*/
|
||||
struct ble_ll_resolv_entry *
|
||||
ble_ll_resolv_list_find(const uint8_t *addr, uint8_t addr_type)
|
||||
{
|
||||
int i;
|
||||
struct ble_ll_resolv_entry *rl;
|
||||
|
||||
rl = &g_ble_ll_resolv_list[0];
|
||||
for (i = 0; i < g_ble_ll_resolv_data.rl_cnt; ++i) {
|
||||
if ((rl->rl_addr_type == addr_type) &&
|
||||
(!memcmp(&rl->rl_identity_addr[0], addr, BLE_DEV_ADDR_LEN))) {
|
||||
return rl;
|
||||
}
|
||||
++rl;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a device to the resolving list
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int
|
||||
ble_ll_resolv_list_add(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
const struct ble_hci_le_add_resolv_list_cp *cmd = (const void *) cmdbuf;
|
||||
struct ble_ll_resolv_entry *rl;
|
||||
int rc = BLE_ERR_SUCCESS;
|
||||
|
||||
if (len != sizeof(*cmd)) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
/* Must be in proper state */
|
||||
if (!ble_ll_resolv_list_chg_allowed()) {
|
||||
return BLE_ERR_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
/* Check if we have any open entries */
|
||||
if (g_ble_ll_resolv_data.rl_cnt >= g_ble_ll_resolv_data.rl_size) {
|
||||
return BLE_ERR_MEM_CAPACITY;
|
||||
}
|
||||
|
||||
/* spec is not clear on how to handle this but make sure host is aware
|
||||
* that new keys are not used in that case
|
||||
*/
|
||||
if (ble_ll_is_on_resolv_list(cmd->peer_id_addr, cmd->peer_addr_type)) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
/* we keep this sorted in a way that entries with peer_irk are first */
|
||||
if (ble_ll_resolv_irk_nonzero(cmd->peer_irk)) {
|
||||
memmove(&g_ble_ll_resolv_list[g_ble_ll_resolv_data.rl_cnt_hw + 1],
|
||||
&g_ble_ll_resolv_list[g_ble_ll_resolv_data.rl_cnt_hw],
|
||||
(g_ble_ll_resolv_data.rl_cnt - g_ble_ll_resolv_data.rl_cnt_hw) *
|
||||
sizeof(g_ble_ll_resolv_list[0]));
|
||||
rl = &g_ble_ll_resolv_list[g_ble_ll_resolv_data.rl_cnt_hw];
|
||||
} else {
|
||||
rl = &g_ble_ll_resolv_list[g_ble_ll_resolv_data.rl_cnt];
|
||||
}
|
||||
|
||||
memset (rl, 0, sizeof(*rl));
|
||||
rl->rl_addr_type = cmd->peer_addr_type;
|
||||
memcpy(rl->rl_identity_addr, cmd->peer_id_addr, BLE_DEV_ADDR_LEN);
|
||||
|
||||
if (ble_ll_resolv_irk_nonzero(cmd->peer_irk)) {
|
||||
swap_buf(rl->rl_peer_irk, cmd->peer_irk, 16);
|
||||
rl->rl_has_peer = 1;
|
||||
|
||||
/* generate peer RPA now, those will be updated by timer when
|
||||
* resolution is enabled
|
||||
*/
|
||||
ble_ll_resolv_gen_priv_addr(rl, 0);
|
||||
}
|
||||
|
||||
if (ble_ll_resolv_irk_nonzero(cmd->local_irk)) {
|
||||
swap_buf(rl->rl_local_irk, cmd->local_irk, 16);
|
||||
rl->rl_has_local = 1;
|
||||
|
||||
/* generate local RPA now, those will be updated by timer when
|
||||
* resolution is enabled
|
||||
*/
|
||||
ble_ll_resolv_gen_priv_addr(rl, 1);
|
||||
}
|
||||
|
||||
/* By default use privacy network mode */
|
||||
rl->rl_priv_mode = BLE_HCI_PRIVACY_NETWORK;
|
||||
|
||||
/* Add peers IRKs to HW resolving list. Should always succeed since we
|
||||
* already checked if there is room for it.
|
||||
*/
|
||||
if (rl->rl_has_peer) {
|
||||
rc = ble_hw_resolv_list_add(rl->rl_peer_irk);
|
||||
BLE_LL_ASSERT(rc == BLE_ERR_SUCCESS);
|
||||
g_ble_ll_resolv_data.rl_cnt_hw++;
|
||||
}
|
||||
|
||||
g_ble_ll_resolv_data.rl_cnt++;
|
||||
|
||||
/* start RPA timer if this was first element added to RL */
|
||||
if (g_ble_ll_resolv_data.rl_cnt == 1) {
|
||||
ble_npl_callout_reset(&g_ble_ll_resolv_data.rpa_timer,
|
||||
g_ble_ll_resolv_data.rpa_tmo);
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a device from the resolving list
|
||||
*
|
||||
* @param cmdbuf
|
||||
*
|
||||
* @return int 0: success, BLE error code otherwise
|
||||
*/
|
||||
int
|
||||
ble_ll_resolv_list_rmv(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
const struct ble_hci_le_rmv_resolve_list_cp *cmd = (const void *) cmdbuf;
|
||||
int position;
|
||||
|
||||
if (len != sizeof(*cmd)) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
/* Must be in proper state */
|
||||
if (!ble_ll_resolv_list_chg_allowed()) {
|
||||
return BLE_ERR_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
/* Remove from IRK records */
|
||||
position = ble_ll_is_on_resolv_list(cmd->peer_id_addr, cmd->peer_addr_type);
|
||||
if (position) {
|
||||
BLE_LL_ASSERT(position <= g_ble_ll_resolv_data.rl_cnt);
|
||||
|
||||
memmove(&g_ble_ll_resolv_list[position - 1],
|
||||
&g_ble_ll_resolv_list[position],
|
||||
(g_ble_ll_resolv_data.rl_cnt - position) *
|
||||
sizeof(g_ble_ll_resolv_list[0]));
|
||||
g_ble_ll_resolv_data.rl_cnt--;
|
||||
|
||||
/* Remove from HW list */
|
||||
if (position <= g_ble_ll_resolv_data.rl_cnt_hw) {
|
||||
ble_hw_resolv_list_rmv(position - 1);
|
||||
g_ble_ll_resolv_data.rl_cnt_hw--;
|
||||
}
|
||||
|
||||
/* stop RPA timer if list is empty */
|
||||
if (g_ble_ll_resolv_data.rl_cnt == 0) {
|
||||
ble_npl_callout_stop(&g_ble_ll_resolv_data.rpa_timer);
|
||||
}
|
||||
|
||||
return BLE_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
return BLE_ERR_UNK_CONN_ID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to enable or disable address resolution in the controller
|
||||
*
|
||||
* @param cmdbuf
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int
|
||||
ble_ll_resolv_enable_cmd(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
const struct ble_hci_le_set_addr_res_en_cp *cmd = (const void *) cmdbuf;
|
||||
|
||||
if (len != sizeof(*cmd)) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
if (ble_ll_is_controller_busy()) {
|
||||
return BLE_ERR_CMD_DISALLOWED;
|
||||
|
||||
}
|
||||
|
||||
if (cmd->enable > 1) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
g_ble_ll_resolv_data.addr_res_enabled = cmd->enable;
|
||||
|
||||
return BLE_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_resolv_peer_addr_rd(const uint8_t *cmdbuf, uint8_t len,
|
||||
uint8_t *rspbuf, uint8_t *rsplen)
|
||||
{
|
||||
const struct ble_hci_le_rd_peer_recolv_addr_cp *cmd = (const void *) cmdbuf;
|
||||
struct ble_hci_le_rd_peer_recolv_addr_rp *rsp = (void *) rspbuf;
|
||||
struct ble_ll_resolv_entry *rl;
|
||||
int rc;
|
||||
|
||||
if (len != sizeof(*cmd)) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
rl = ble_ll_resolv_list_find(cmd->peer_id_addr, cmd->peer_addr_type);
|
||||
if (rl) {
|
||||
memcpy(rsp->rpa, rl->rl_peer_rpa, BLE_DEV_ADDR_LEN);
|
||||
rc = BLE_ERR_SUCCESS;
|
||||
} else {
|
||||
memset(rsp->rpa, 0, BLE_DEV_ADDR_LEN);
|
||||
rc = BLE_ERR_UNK_CONN_ID;
|
||||
}
|
||||
|
||||
*rsplen = sizeof(*rsp);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_resolv_local_addr_rd(const uint8_t *cmdbuf, uint8_t len,
|
||||
uint8_t *rspbuf, uint8_t *rsplen)
|
||||
{
|
||||
const struct ble_hci_le_rd_local_recolv_addr_cp *cmd = (const void *) cmdbuf;
|
||||
struct ble_hci_le_rd_local_recolv_addr_rp *rsp = (void *) rspbuf;
|
||||
struct ble_ll_resolv_entry *rl;
|
||||
int rc;
|
||||
|
||||
if (len != sizeof(*cmd)) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
rl = ble_ll_resolv_list_find(cmd->peer_id_addr, cmd->peer_addr_type);
|
||||
if (rl) {
|
||||
memcpy(rsp->rpa, rl->rl_local_rpa, BLE_DEV_ADDR_LEN);
|
||||
rc = BLE_ERR_SUCCESS;
|
||||
} else {
|
||||
memset(rsp->rpa, 0, BLE_DEV_ADDR_LEN);
|
||||
rc = BLE_ERR_UNK_CONN_ID;
|
||||
}
|
||||
|
||||
*rsplen = sizeof(*rsp);
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the resolvable private address timeout.
|
||||
*
|
||||
* @param cmdbuf
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int
|
||||
ble_ll_resolv_set_rpa_tmo(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
const struct ble_hci_le_set_rpa_tmo_cp *cmd = (const void *)cmdbuf;
|
||||
uint16_t tmo_secs;
|
||||
|
||||
if (len != sizeof(*cmd)) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
tmo_secs = le16toh(cmd->rpa_timeout);
|
||||
if (!((tmo_secs > 0) && (tmo_secs <= 0xA1B8))) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
g_ble_ll_resolv_data.rpa_tmo = ble_npl_time_ms_to_ticks32(tmo_secs * 1000);
|
||||
|
||||
/* restart timer if there is something on RL */
|
||||
if (g_ble_ll_resolv_data.rl_cnt) {
|
||||
ble_npl_callout_reset(&g_ble_ll_resolv_data.rpa_timer,
|
||||
g_ble_ll_resolv_data.rpa_tmo);
|
||||
}
|
||||
|
||||
return BLE_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_resolve_set_priv_mode(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
const struct ble_hci_le_set_privacy_mode_cp *cmd = (const void *) cmdbuf;
|
||||
struct ble_ll_resolv_entry *rl;
|
||||
|
||||
if (ble_ll_is_controller_busy()) {
|
||||
return BLE_ERR_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
if (len != sizeof(*cmd)) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
rl = ble_ll_resolv_list_find(cmd->peer_id_addr, cmd->peer_id_addr_type);
|
||||
if (!rl) {
|
||||
return BLE_ERR_UNK_CONN_ID;
|
||||
}
|
||||
|
||||
if (cmd->mode > BLE_HCI_PRIVACY_DEVICE) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
rl->rl_priv_mode = cmd->mode;
|
||||
|
||||
return BLE_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Resolvable Private address timeout, in os ticks
|
||||
*
|
||||
*
|
||||
* @return uint32_t
|
||||
*/
|
||||
uint32_t
|
||||
ble_ll_resolv_get_rpa_tmo(void)
|
||||
{
|
||||
return g_ble_ll_resolv_data.rpa_tmo;
|
||||
}
|
||||
|
||||
void
|
||||
ble_ll_resolv_get_priv_addr(struct ble_ll_resolv_entry *rl, int local,
|
||||
uint8_t *addr)
|
||||
{
|
||||
os_sr_t sr;
|
||||
|
||||
BLE_LL_ASSERT(rl != NULL);
|
||||
BLE_LL_ASSERT(addr != NULL);
|
||||
|
||||
OS_ENTER_CRITICAL(sr);
|
||||
if (local) {
|
||||
BLE_LL_ASSERT(rl->rl_has_local);
|
||||
memcpy(addr, rl->rl_local_rpa, BLE_DEV_ADDR_LEN);
|
||||
} else {
|
||||
BLE_LL_ASSERT(rl->rl_has_peer);
|
||||
memcpy(addr, rl->rl_peer_rpa, BLE_DEV_ADDR_LEN);
|
||||
}
|
||||
|
||||
OS_EXIT_CRITICAL(sr);
|
||||
}
|
||||
|
||||
void
|
||||
ble_ll_resolv_set_peer_rpa(int index, uint8_t *rpa)
|
||||
{
|
||||
os_sr_t sr;
|
||||
struct ble_ll_resolv_entry *rl;
|
||||
|
||||
OS_ENTER_CRITICAL(sr);
|
||||
rl = &g_ble_ll_resolv_list[index];
|
||||
memcpy(rl->rl_peer_rpa, rpa, BLE_DEV_ADDR_LEN);
|
||||
OS_EXIT_CRITICAL(sr);
|
||||
}
|
||||
|
||||
void
|
||||
ble_ll_resolv_set_local_rpa(int index, uint8_t *rpa)
|
||||
{
|
||||
os_sr_t sr;
|
||||
struct ble_ll_resolv_entry *rl;
|
||||
|
||||
OS_ENTER_CRITICAL(sr);
|
||||
rl = &g_ble_ll_resolv_list[index];
|
||||
memcpy(rl->rl_local_rpa, rpa, BLE_DEV_ADDR_LEN);
|
||||
OS_EXIT_CRITICAL(sr);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a resolvable private address.
|
||||
*
|
||||
* @param addr
|
||||
* @param addr_type
|
||||
* @param rpa
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int
|
||||
ble_ll_resolv_gen_rpa(uint8_t *addr, uint8_t addr_type, uint8_t *rpa, int local)
|
||||
{
|
||||
struct ble_ll_resolv_entry *rl;
|
||||
|
||||
rl = ble_ll_resolv_list_find(addr, addr_type);
|
||||
if (rl) {
|
||||
if ((local && rl->rl_has_local) || (!local && rl->rl_has_peer)) {
|
||||
ble_ll_resolv_get_priv_addr(rl, local, rpa);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolve a Resolvable Private Address
|
||||
*
|
||||
* @param rpa
|
||||
* @param index
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int
|
||||
ble_ll_resolv_rpa(const uint8_t *rpa, const uint8_t *irk)
|
||||
{
|
||||
int rc;
|
||||
const uint32_t *irk32;
|
||||
uint32_t *key32;
|
||||
uint32_t *pt32;
|
||||
struct ble_encryption_block ecb;
|
||||
|
||||
irk32 = (const uint32_t *)irk;
|
||||
key32 = (uint32_t *)&ecb.key[0];
|
||||
|
||||
key32[0] = irk32[0];
|
||||
key32[1] = irk32[1];
|
||||
key32[2] = irk32[2];
|
||||
key32[3] = irk32[3];
|
||||
|
||||
pt32 = (uint32_t *)&ecb.plain_text[0];
|
||||
pt32[0] = 0;
|
||||
pt32[1] = 0;
|
||||
pt32[2] = 0;
|
||||
pt32[3] = 0;
|
||||
|
||||
ecb.plain_text[15] = rpa[3];
|
||||
ecb.plain_text[14] = rpa[4];
|
||||
ecb.plain_text[13] = rpa[5];
|
||||
|
||||
ble_hw_encrypt_block(&ecb);
|
||||
if ((ecb.cipher_text[15] == rpa[0]) && (ecb.cipher_text[14] == rpa[1]) &&
|
||||
(ecb.cipher_text[13] == rpa[2])) {
|
||||
rc = 1;
|
||||
} else {
|
||||
rc = 0;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
int
|
||||
ble_ll_resolv_peer_rpa_any(const uint8_t *rpa)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < g_ble_ll_resolv_data.rl_cnt_hw; i++) {
|
||||
if (ble_ll_resolv_rpa(rpa, g_ble_ll_resolv_list[i].rl_peer_irk)) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not address resolution is enabled.
|
||||
*
|
||||
* @return uint8_t
|
||||
*/
|
||||
uint8_t
|
||||
ble_ll_resolv_enabled(void)
|
||||
{
|
||||
return g_ble_ll_resolv_data.addr_res_enabled;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to reset private address resolution module.
|
||||
*/
|
||||
void
|
||||
ble_ll_resolv_list_reset(void)
|
||||
{
|
||||
g_ble_ll_resolv_data.addr_res_enabled = 0;
|
||||
ble_npl_callout_stop(&g_ble_ll_resolv_data.rpa_timer);
|
||||
ble_ll_resolv_list_clr();
|
||||
ble_ll_resolv_init();
|
||||
}
|
||||
|
||||
void
|
||||
ble_ll_resolv_init(void)
|
||||
{
|
||||
uint8_t hw_size;
|
||||
|
||||
/* Default is 15 minutes */
|
||||
g_ble_ll_resolv_data.rpa_tmo = ble_npl_time_ms_to_ticks32(15 * 60 * 1000);
|
||||
|
||||
hw_size = ble_hw_resolv_list_size();
|
||||
if (hw_size > MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE)) {
|
||||
hw_size = MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE);
|
||||
}
|
||||
g_ble_ll_resolv_data.rl_size = hw_size;
|
||||
|
||||
ble_npl_callout_init(&g_ble_ll_resolv_data.rpa_timer,
|
||||
&g_ble_ll_data.ll_evq,
|
||||
ble_ll_resolv_rpa_timer_cb,
|
||||
NULL);
|
||||
}
|
||||
|
||||
#endif /* if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY) */
|
||||
#endif
|
||||
@@ -0,0 +1,349 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
#ifndef ESP_PLATFORM
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
#include "nimble/porting/nimble/include/syscfg/syscfg.h"
|
||||
#include "nimble/porting/nimble/include/os/os_cputime.h"
|
||||
#include "../include/controller/ble_phy.h"
|
||||
#include "../include/controller/ble_ll.h"
|
||||
#include "../include/controller/ble_ll_sched.h"
|
||||
#include "../include/controller/ble_ll_rfmgmt.h"
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_RFMGMT_ENABLE_TIME) > 0
|
||||
|
||||
enum ble_ll_rfmgmt_state {
|
||||
RFMGMT_STATE_OFF = 0,
|
||||
RFMGMT_STATE_ENABLING = 1,
|
||||
RFMGMT_STATE_ENABLED = 2,
|
||||
};
|
||||
|
||||
struct ble_ll_rfmgmt_data {
|
||||
enum ble_ll_rfmgmt_state state;
|
||||
uint16_t ticks_to_enabled;
|
||||
|
||||
struct hal_timer timer;
|
||||
bool timer_scheduled;
|
||||
uint32_t timer_scheduled_at;
|
||||
|
||||
bool enable_scan;
|
||||
bool enable_sched;
|
||||
uint32_t enable_scan_at;
|
||||
uint32_t enable_sched_at;
|
||||
|
||||
uint32_t enabled_at;
|
||||
|
||||
struct ble_npl_event release_ev;
|
||||
};
|
||||
|
||||
static struct ble_ll_rfmgmt_data g_ble_ll_rfmgmt_data;
|
||||
|
||||
static void
|
||||
ble_ll_rfmgmt_enable(void)
|
||||
{
|
||||
OS_ASSERT_CRITICAL();
|
||||
|
||||
if (g_ble_ll_rfmgmt_data.state == RFMGMT_STATE_OFF) {
|
||||
g_ble_ll_rfmgmt_data.state = RFMGMT_STATE_ENABLING;
|
||||
g_ble_ll_rfmgmt_data.enabled_at = os_cputime_get32();
|
||||
ble_phy_rfclk_enable();
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ble_ll_rfmgmt_disable(void)
|
||||
{
|
||||
OS_ASSERT_CRITICAL();
|
||||
|
||||
if (g_ble_ll_rfmgmt_data.state != RFMGMT_STATE_OFF) {
|
||||
ble_phy_rfclk_disable();
|
||||
g_ble_ll_rfmgmt_data.state = RFMGMT_STATE_OFF;
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
ble_ll_rfmgmt_timer_reschedule(void)
|
||||
{
|
||||
struct ble_ll_rfmgmt_data *rfmgmt = &g_ble_ll_rfmgmt_data;
|
||||
uint32_t enable_at;
|
||||
|
||||
/* Figure out when we need to enable RF */
|
||||
if (rfmgmt->enable_scan && rfmgmt->enable_sched) {
|
||||
if (CPUTIME_LT(rfmgmt->enable_scan_at, rfmgmt->enable_sched_at)) {
|
||||
enable_at = rfmgmt->enable_scan_at;
|
||||
} else {
|
||||
enable_at = rfmgmt->enable_sched_at;
|
||||
}
|
||||
} else if (rfmgmt->enable_scan) {
|
||||
enable_at = rfmgmt->enable_scan_at;
|
||||
} else if (rfmgmt->enable_sched) {
|
||||
enable_at = rfmgmt->enable_sched_at;
|
||||
} else {
|
||||
rfmgmt->timer_scheduled = false;
|
||||
os_cputime_timer_stop(&rfmgmt->timer);
|
||||
return;
|
||||
}
|
||||
|
||||
if (rfmgmt->timer_scheduled) {
|
||||
/*
|
||||
* If there is timer already scheduled at the same time we do not need
|
||||
* to do anything. Otherwise we need to stop timer and schedule it again
|
||||
* regardless if it's earlier or later to make sure it fires at the time
|
||||
* something expects it.
|
||||
*/
|
||||
|
||||
if (rfmgmt->timer_scheduled_at == enable_at) {
|
||||
return;
|
||||
}
|
||||
|
||||
rfmgmt->timer_scheduled = false;
|
||||
os_cputime_timer_stop(&rfmgmt->timer);
|
||||
}
|
||||
|
||||
/*
|
||||
* In case timer was requested to be enabled before current time, just make
|
||||
* sure it's enabled and assume caller can deal with this. This will happen
|
||||
* if something is scheduled "now" since "enable_at" is in the past, but in
|
||||
* such case it's absolutely harmless since we already have clock enabled
|
||||
* and this will do nothing.
|
||||
*/
|
||||
if (CPUTIME_LEQ(enable_at, os_cputime_get32())) {
|
||||
ble_ll_rfmgmt_enable();
|
||||
return;
|
||||
}
|
||||
|
||||
rfmgmt->timer_scheduled = true;
|
||||
rfmgmt->timer_scheduled_at = enable_at;
|
||||
os_cputime_timer_start(&rfmgmt->timer, enable_at);
|
||||
}
|
||||
|
||||
static void
|
||||
ble_ll_rfmgmt_timer_exp(void *arg)
|
||||
{
|
||||
g_ble_ll_rfmgmt_data.timer_scheduled = false;
|
||||
ble_ll_rfmgmt_enable();
|
||||
}
|
||||
|
||||
static void
|
||||
ble_ll_rfmgmt_release_ev(struct ble_npl_event *ev)
|
||||
{
|
||||
struct ble_ll_rfmgmt_data *rfmgmt = &g_ble_ll_rfmgmt_data;
|
||||
uint32_t now;
|
||||
bool can_disable;
|
||||
uint8_t lls;
|
||||
os_sr_t sr;
|
||||
|
||||
OS_ENTER_CRITICAL(sr);
|
||||
|
||||
now = os_cputime_get32();
|
||||
|
||||
can_disable = true;
|
||||
lls = ble_ll_state_get();
|
||||
|
||||
if (rfmgmt->enable_scan && CPUTIME_GEQ(now, rfmgmt->enable_scan_at)) {
|
||||
/* Blocked by scan */
|
||||
can_disable = false;
|
||||
} else if (rfmgmt->enable_sched && CPUTIME_GEQ(now, rfmgmt->enable_sched_at)) {
|
||||
/* Blocked by scheduler item */
|
||||
can_disable = false;
|
||||
} else if (lls != BLE_LL_STATE_STANDBY) {
|
||||
/* Blocked by LL state */
|
||||
can_disable = false;
|
||||
}
|
||||
|
||||
if (can_disable) {
|
||||
ble_ll_rfmgmt_disable();
|
||||
}
|
||||
|
||||
OS_EXIT_CRITICAL(sr);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
ble_ll_rfmgmt_ticks_to_enabled(void)
|
||||
{
|
||||
struct ble_ll_rfmgmt_data *rfmgmt = &g_ble_ll_rfmgmt_data;
|
||||
uint32_t rem_ticks;
|
||||
uint32_t now;
|
||||
|
||||
switch (rfmgmt->state) {
|
||||
case RFMGMT_STATE_OFF:
|
||||
rem_ticks = rfmgmt->ticks_to_enabled;
|
||||
break;
|
||||
case RFMGMT_STATE_ENABLING:
|
||||
now = os_cputime_get32();
|
||||
if (CPUTIME_LT(now, rfmgmt->enabled_at + rfmgmt->ticks_to_enabled)) {
|
||||
rem_ticks = rfmgmt->enabled_at + rfmgmt->ticks_to_enabled - now;
|
||||
break;
|
||||
}
|
||||
rfmgmt->state = RFMGMT_STATE_ENABLED;
|
||||
/* Else falls through. */
|
||||
/* no break */
|
||||
case RFMGMT_STATE_ENABLED:
|
||||
rem_ticks = 0;
|
||||
break;
|
||||
default:
|
||||
BLE_LL_ASSERT(0);
|
||||
rem_ticks = 0;
|
||||
break;
|
||||
}
|
||||
|
||||
return rem_ticks;
|
||||
}
|
||||
|
||||
void
|
||||
ble_ll_rfmgmt_init(void)
|
||||
{
|
||||
struct ble_ll_rfmgmt_data *rfmgmt = &g_ble_ll_rfmgmt_data;
|
||||
|
||||
rfmgmt->state = RFMGMT_STATE_OFF;
|
||||
|
||||
rfmgmt->ticks_to_enabled =
|
||||
ble_ll_usecs_to_ticks_round_up(MYNEWT_VAL(BLE_LL_RFMGMT_ENABLE_TIME));
|
||||
|
||||
rfmgmt->timer_scheduled = false;
|
||||
os_cputime_timer_init(&rfmgmt->timer, ble_ll_rfmgmt_timer_exp, NULL);
|
||||
|
||||
ble_npl_event_init(&rfmgmt->release_ev, ble_ll_rfmgmt_release_ev, NULL);
|
||||
}
|
||||
|
||||
void
|
||||
ble_ll_rfmgmt_reset(void)
|
||||
{
|
||||
struct ble_ll_rfmgmt_data *rfmgmt = &g_ble_ll_rfmgmt_data;
|
||||
|
||||
rfmgmt->timer_scheduled = false;
|
||||
rfmgmt->timer_scheduled_at = 0;
|
||||
os_cputime_timer_stop(&rfmgmt->timer);
|
||||
|
||||
ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &rfmgmt->release_ev);
|
||||
|
||||
ble_ll_rfmgmt_disable();
|
||||
|
||||
rfmgmt->enable_scan = false;
|
||||
rfmgmt->enable_scan_at = 0;
|
||||
rfmgmt->enable_sched = false;
|
||||
rfmgmt->enable_sched_at = 0;
|
||||
|
||||
rfmgmt->enabled_at = 0;
|
||||
}
|
||||
|
||||
void
|
||||
ble_ll_rfmgmt_scan_changed(bool enabled, uint32_t next_window)
|
||||
{
|
||||
struct ble_ll_rfmgmt_data *rfmgmt = &g_ble_ll_rfmgmt_data;
|
||||
os_sr_t sr;
|
||||
|
||||
OS_ENTER_CRITICAL(sr);
|
||||
|
||||
rfmgmt->enable_scan = enabled;
|
||||
rfmgmt->enable_scan_at = next_window - rfmgmt->ticks_to_enabled;
|
||||
|
||||
ble_ll_rfmgmt_timer_reschedule();
|
||||
|
||||
OS_EXIT_CRITICAL(sr);
|
||||
}
|
||||
|
||||
void
|
||||
ble_ll_rfmgmt_sched_changed(struct ble_ll_sched_item *first)
|
||||
{
|
||||
struct ble_ll_rfmgmt_data *rfmgmt = &g_ble_ll_rfmgmt_data;
|
||||
os_sr_t sr;
|
||||
|
||||
OS_ENTER_CRITICAL(sr);
|
||||
|
||||
rfmgmt->enable_sched = (first != NULL);
|
||||
if (first) {
|
||||
rfmgmt->enable_sched_at = first->start_time - rfmgmt->ticks_to_enabled;
|
||||
}
|
||||
|
||||
ble_ll_rfmgmt_timer_reschedule();
|
||||
|
||||
OS_EXIT_CRITICAL(sr);
|
||||
}
|
||||
|
||||
void
|
||||
ble_ll_rfmgmt_release(void)
|
||||
{
|
||||
struct ble_ll_rfmgmt_data *rfmgmt = &g_ble_ll_rfmgmt_data;
|
||||
os_sr_t sr;
|
||||
|
||||
OS_ENTER_CRITICAL(sr);
|
||||
|
||||
ble_npl_eventq_remove(&g_ble_ll_data.ll_evq, &rfmgmt->release_ev);
|
||||
|
||||
if (g_ble_ll_rfmgmt_data.state != RFMGMT_STATE_OFF) {
|
||||
ble_npl_eventq_put(&g_ble_ll_data.ll_evq, &rfmgmt->release_ev);
|
||||
}
|
||||
|
||||
OS_EXIT_CRITICAL(sr);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
ble_ll_rfmgmt_enable_now(void)
|
||||
{
|
||||
struct ble_ll_rfmgmt_data *rfmgmt = &g_ble_ll_rfmgmt_data;
|
||||
uint32_t enabled_at;
|
||||
os_sr_t sr;
|
||||
|
||||
OS_ENTER_CRITICAL(sr);
|
||||
|
||||
ble_ll_rfmgmt_enable();
|
||||
|
||||
if (rfmgmt->state == RFMGMT_STATE_ENABLED) {
|
||||
enabled_at = os_cputime_get32();
|
||||
} else {
|
||||
enabled_at = rfmgmt->enabled_at + rfmgmt->ticks_to_enabled + 1;
|
||||
}
|
||||
|
||||
OS_EXIT_CRITICAL(sr);
|
||||
|
||||
return enabled_at;
|
||||
}
|
||||
|
||||
bool
|
||||
ble_ll_rfmgmt_is_enabled(void)
|
||||
{
|
||||
bool ret;
|
||||
|
||||
OS_ASSERT_CRITICAL();
|
||||
|
||||
ret = ble_ll_rfmgmt_ticks_to_enabled() == 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
void
|
||||
ble_ll_rfmgmt_init(void)
|
||||
{
|
||||
static bool enabled = false;
|
||||
|
||||
if (!enabled) {
|
||||
ble_phy_rfclk_enable();
|
||||
}
|
||||
|
||||
enabled = true;
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
3981
lib/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_scan.c
Normal file
3981
lib/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_scan.c
Normal file
File diff suppressed because it is too large
Load Diff
1838
lib/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_sched.c
Normal file
1838
lib/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_sched.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,461 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
#ifndef ESP_PLATFORM
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "nimble/nimble/include/nimble/ble.h"
|
||||
#include "nimble/nimble/include/nimble/nimble_opt.h"
|
||||
#include "nimble/nimble/include/nimble/hci_common.h"
|
||||
#include "../include/controller/ble_ll.h"
|
||||
#include "../include/controller/ble_ll_hci.h"
|
||||
|
||||
/* Octet 0 */
|
||||
#define BLE_SUPP_CMD_DISCONNECT (1 << 5)
|
||||
#define BLE_LL_SUPP_CMD_OCTET_0 (BLE_SUPP_CMD_DISCONNECT)
|
||||
|
||||
/* Octet 5 */
|
||||
#define BLE_SUPP_CMD_SET_EVENT_MASK (1 << 6)
|
||||
#define BLE_LL_SUPP_CMD_OCTET_5 (BLE_SUPP_CMD_SET_EVENT_MASK)
|
||||
|
||||
/* Octet 10 */
|
||||
#define BLE_SUPP_CMD_RD_TX_PWR (0 << 2)
|
||||
#define BLE_LL_SUPP_CMD_OCTET_10 (BLE_SUPP_CMD_RD_TX_PWR)
|
||||
|
||||
/* Octet 14 */
|
||||
#define BLE_SUPP_CMD_RD_LOC_VER (1 << 3)
|
||||
#define BLE_SUPP_CMD_RD_LOC_SUPP_FEAT (1 << 5)
|
||||
#define BLE_LL_SUPP_CMD_OCTET_14 \
|
||||
( \
|
||||
BLE_SUPP_CMD_RD_LOC_VER | \
|
||||
BLE_SUPP_CMD_RD_LOC_SUPP_FEAT \
|
||||
)
|
||||
|
||||
/* Octet 15 */
|
||||
#define BLE_SUPP_CMD_RD_BD_ADDR (1 << 1)
|
||||
#define BLE_SUPP_CMD_RD_RSSI (1 << 5)
|
||||
|
||||
#define BLE_LL_SUPP_CMD_OCTET_15 \
|
||||
( \
|
||||
BLE_SUPP_CMD_RD_BD_ADDR | \
|
||||
BLE_SUPP_CMD_RD_RSSI \
|
||||
)
|
||||
|
||||
/* Octet 25 */
|
||||
#define BLE_SUPP_CMD_LE_SET_EV_MASK (1 << 0)
|
||||
#define BLE_SUPP_CMD_LE_RD_BUF_SIZE (1 << 1)
|
||||
#define BLE_SUPP_CMD_LE_RD_LOC_FEAT (1 << 2)
|
||||
#define BLE_SUPP_CMD_LE_SET_RAND_ADDR (1 << 4)
|
||||
#define BLE_SUPP_CMD_LE_SET_ADV_PARAMS (1 << 5)
|
||||
#define BLE_SUPP_CMD_LE_SET_ADV_TX_PWR (1 << 6)
|
||||
#define BLE_SUPP_CMD_LE_SET_ADV_DATA (1 << 7)
|
||||
|
||||
#define BLE_LL_SUPP_CMD_OCTET_25 \
|
||||
( \
|
||||
BLE_SUPP_CMD_LE_SET_EV_MASK | \
|
||||
BLE_SUPP_CMD_LE_RD_BUF_SIZE | \
|
||||
BLE_SUPP_CMD_LE_RD_LOC_FEAT | \
|
||||
BLE_SUPP_CMD_LE_SET_RAND_ADDR | \
|
||||
BLE_SUPP_CMD_LE_SET_ADV_PARAMS | \
|
||||
BLE_SUPP_CMD_LE_SET_ADV_TX_PWR | \
|
||||
BLE_SUPP_CMD_LE_SET_ADV_DATA \
|
||||
)
|
||||
|
||||
/* Octet 26 */
|
||||
#define BLE_SUPP_CMD_LE_SET_SCAN_RSP_DATA (1 << 0)
|
||||
#define BLE_SUPP_CMD_LE_SET_ADV_ENABLE (1 << 1)
|
||||
#define BLE_SUPP_CMD_LE_SET_SCAN_PARAMS (1 << 2)
|
||||
#define BLE_SUPP_CMD_LE_SET_SCAN_ENABLE (1 << 3)
|
||||
#define BLE_SUPP_CMD_LE_CREATE_CONN (1 << 4)
|
||||
#define BLE_SUPP_CMD_LE_CREATE_CONN_CANCEL (1 << 5)
|
||||
#define BLE_SUPP_CMD_LE_RD_WHITELIST_SIZE (1 << 6)
|
||||
#define BLE_SUPP_CMD_LE_CLR_WHITELIST (1 << 7)
|
||||
|
||||
#define BLE_LL_SUPP_CMD_OCTET_26 \
|
||||
( \
|
||||
BLE_SUPP_CMD_LE_SET_SCAN_RSP_DATA | \
|
||||
BLE_SUPP_CMD_LE_SET_ADV_ENABLE | \
|
||||
BLE_SUPP_CMD_LE_SET_SCAN_PARAMS | \
|
||||
BLE_SUPP_CMD_LE_SET_SCAN_ENABLE | \
|
||||
BLE_SUPP_CMD_LE_CREATE_CONN | \
|
||||
BLE_SUPP_CMD_LE_CREATE_CONN_CANCEL | \
|
||||
BLE_SUPP_CMD_LE_RD_WHITELIST_SIZE | \
|
||||
BLE_SUPP_CMD_LE_CLR_WHITELIST \
|
||||
)
|
||||
|
||||
/* Octet 27 */
|
||||
#define BLE_SUPP_CMD_LE_ADD_DEV_WHITELIST (1 << 0)
|
||||
#define BLE_SUPP_CMD_LE_RMV_DEV_WHITELIST (1 << 1)
|
||||
#define BLE_SUPP_CMD_LE_CONN_UPDATE (1 << 2)
|
||||
#define BLE_SUPP_CMD_LE_SET_HOST_CHAN_CLASS (1 << 3)
|
||||
#define BLE_SUPP_CMD_LE_RD_CHAN_MAP (1 << 4)
|
||||
#define BLE_SUPP_CMD_LE_RD_REM_USED_FEAT (1 << 5)
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
|
||||
#define BLE_SUPP_CMD_LE_ENCRYPT (1 << 6)
|
||||
#else
|
||||
#define BLE_SUPP_CMD_LE_ENCRYPT (0 << 6)
|
||||
#endif
|
||||
#define BLE_SUPP_CMD_LE_RAND (1 << 7)
|
||||
|
||||
#define BLE_LL_SUPP_CMD_OCTET_27 \
|
||||
( \
|
||||
BLE_SUPP_CMD_LE_ENCRYPT | \
|
||||
BLE_SUPP_CMD_LE_RAND | \
|
||||
BLE_SUPP_CMD_LE_ADD_DEV_WHITELIST | \
|
||||
BLE_SUPP_CMD_LE_RMV_DEV_WHITELIST | \
|
||||
BLE_SUPP_CMD_LE_CONN_UPDATE | \
|
||||
BLE_SUPP_CMD_LE_SET_HOST_CHAN_CLASS | \
|
||||
BLE_SUPP_CMD_LE_RD_CHAN_MAP | \
|
||||
BLE_SUPP_CMD_LE_RD_REM_USED_FEAT \
|
||||
)
|
||||
|
||||
/* Octet 28 */
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_ENCRYPTION)
|
||||
#define BLE_SUPP_CMD_LE_START_ENCRYPT (1 << 0)
|
||||
#define BLE_SUPP_CMD_LE_LTK_REQ_REPLY (1 << 1)
|
||||
#define BLE_SUPP_CMD_LE_LTK_REQ_NEG_REPLY (1 << 2)
|
||||
#else
|
||||
#define BLE_SUPP_CMD_LE_START_ENCRYPT (0 << 0)
|
||||
#define BLE_SUPP_CMD_LE_LTK_REQ_REPLY (0 << 1)
|
||||
#define BLE_SUPP_CMD_LE_LTK_REQ_NEG_REPLY (0 << 2)
|
||||
#endif
|
||||
#define BLE_SUPP_CMD_LE_READ_SUPP_STATES (1 << 3)
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_DTM)
|
||||
#define BLE_SUPP_CMD_LE_RX_TEST (1 << 4)
|
||||
#define BLE_SUPP_CMD_LE_TX_TEST (1 << 5)
|
||||
#define BLE_SUPP_CMD_LE_TEST_END (1 << 6)
|
||||
|
||||
#else
|
||||
#define BLE_SUPP_CMD_LE_RX_TEST (0 << 4)
|
||||
#define BLE_SUPP_CMD_LE_TX_TEST (0 << 5)
|
||||
#define BLE_SUPP_CMD_LE_TEST_END (0 << 6)
|
||||
#endif
|
||||
|
||||
#define BLE_LL_SUPP_CMD_OCTET_28 \
|
||||
( \
|
||||
BLE_SUPP_CMD_LE_START_ENCRYPT | \
|
||||
BLE_SUPP_CMD_LE_LTK_REQ_REPLY | \
|
||||
BLE_SUPP_CMD_LE_LTK_REQ_NEG_REPLY | \
|
||||
BLE_SUPP_CMD_LE_READ_SUPP_STATES | \
|
||||
BLE_SUPP_CMD_LE_RX_TEST | \
|
||||
BLE_SUPP_CMD_LE_TX_TEST | \
|
||||
BLE_SUPP_CMD_LE_TEST_END \
|
||||
)
|
||||
|
||||
/* Octet 33 */
|
||||
#define BLE_SUPP_CMD_LE_REM_CONN_PRR (1 << 4)
|
||||
#define BLE_SUPP_CMD_LE_REM_CONN_PRNR (1 << 5)
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT)
|
||||
#define BLE_SUPP_CMD_LE_SET_DATALEN (1 << 6)
|
||||
#define BLE_SUPP_CMD_LE_RD_SUGG_DATALEN (1 << 7)
|
||||
#else
|
||||
#define BLE_SUPP_CMD_LE_SET_DATALEN (0 << 6)
|
||||
#define BLE_SUPP_CMD_LE_RD_SUGG_DATALEN (0 << 7)
|
||||
#endif
|
||||
|
||||
#define BLE_LL_SUPP_CMD_OCTET_33 \
|
||||
( \
|
||||
BLE_SUPP_CMD_LE_REM_CONN_PRR | \
|
||||
BLE_SUPP_CMD_LE_REM_CONN_PRNR | \
|
||||
BLE_SUPP_CMD_LE_SET_DATALEN | \
|
||||
BLE_SUPP_CMD_LE_RD_SUGG_DATALEN \
|
||||
)
|
||||
|
||||
/* Octet 34 */
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_DATA_LEN_EXT)
|
||||
#define BLE_SUPP_CMD_LE_WR_SUGG_DATALEN (1 << 0)
|
||||
#else
|
||||
#define BLE_SUPP_CMD_LE_WR_SUGG_DATALEN (0 << 0)
|
||||
#endif
|
||||
#define BLE_SUPP_CMD_LE_READ_LOCAL_P256_PK (0 << 1)
|
||||
#define BLE_SUPP_CMD_LE_GENERATE_DH_KEY (0 << 2)
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
|
||||
#define BLE_SUPP_CMD_LE_ADD_RESOLV_LIST (1 << 3)
|
||||
#define BLE_SUPP_CMD_LE_REMOVE_RESOLV_LIST (1 << 4)
|
||||
#define BLE_SUPP_CMD_LE_CLEAR_RESOLV_LIST (1 << 5)
|
||||
#define BLE_SUPP_CMD_LE_RD_RESOLV_SIZE (1 << 6)
|
||||
#define BLE_SUPP_CMD_LE_RD_PEER_RESV_ADDR (1 << 7)
|
||||
#else
|
||||
#define BLE_SUPP_CMD_LE_ADD_RESOLV_LIST (0 << 3)
|
||||
#define BLE_SUPP_CMD_LE_REMOVE_RESOLV_LIST (0 << 4)
|
||||
#define BLE_SUPP_CMD_LE_CLEAR_RESOLV_LIST (0 << 5)
|
||||
#define BLE_SUPP_CMD_LE_RD_RESOLV_SIZE (0 << 6)
|
||||
#define BLE_SUPP_CMD_LE_RD_PEER_RESV_ADDR (0 << 7)
|
||||
#endif
|
||||
|
||||
#define BLE_LL_SUPP_CMD_OCTET_34 \
|
||||
( \
|
||||
BLE_SUPP_CMD_LE_WR_SUGG_DATALEN | \
|
||||
BLE_SUPP_CMD_LE_READ_LOCAL_P256_PK | \
|
||||
BLE_SUPP_CMD_LE_GENERATE_DH_KEY | \
|
||||
BLE_SUPP_CMD_LE_ADD_RESOLV_LIST | \
|
||||
BLE_SUPP_CMD_LE_REMOVE_RESOLV_LIST | \
|
||||
BLE_SUPP_CMD_LE_CLEAR_RESOLV_LIST | \
|
||||
BLE_SUPP_CMD_LE_RD_RESOLV_SIZE | \
|
||||
BLE_SUPP_CMD_LE_RD_PEER_RESV_ADDR \
|
||||
)
|
||||
|
||||
/* Octet 35 */
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
|
||||
#define BLE_SUPP_CMD_LE_RD_LOCAL_RESV_ADDR (1 << 0)
|
||||
#define BLE_SUPP_CMD_LE_SET_ADDR_RES_EN (1 << 1)
|
||||
#define BLE_SUPP_CMD_LE_SET_RESV_ADDR_TMO (1 << 2)
|
||||
#else
|
||||
#define BLE_SUPP_CMD_LE_RD_LOCAL_RESV_ADDR (0 << 0)
|
||||
#define BLE_SUPP_CMD_LE_SET_ADDR_RES_EN (0 << 1)
|
||||
#define BLE_SUPP_CMD_LE_SET_RESV_ADDR_TMO (0 << 2)
|
||||
#endif
|
||||
#define BLE_SUPP_CMD_LE_RD_MAX_DATALEN (1 << 3)
|
||||
#if (BLE_LL_BT5_PHY_SUPPORTED == 1)
|
||||
#define BLE_SUPP_CMD_LE_READ_PHY (1 << 4)
|
||||
#define BLE_SUPP_CMD_LE_SET_DEFAULT_PHY (1 << 5)
|
||||
#define BLE_SUPP_CMD_LE_SET_PHY (1 << 6)
|
||||
#else
|
||||
#define BLE_SUPP_CMD_LE_READ_PHY (0 << 4)
|
||||
#define BLE_SUPP_CMD_LE_SET_DEFAULT_PHY (0 << 5)
|
||||
#define BLE_SUPP_CMD_LE_SET_PHY (0 << 6)
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_DTM)
|
||||
#define BLE_SUPP_CMD_LE_ENHANCED_RX_TEST (1 << 7)
|
||||
#else
|
||||
#define BLE_SUPP_CMD_LE_ENHANCED_RX_TEST (0 << 7)
|
||||
#endif
|
||||
|
||||
#define BLE_LL_SUPP_CMD_OCTET_35 \
|
||||
( \
|
||||
BLE_SUPP_CMD_LE_RD_LOCAL_RESV_ADDR | \
|
||||
BLE_SUPP_CMD_LE_SET_ADDR_RES_EN | \
|
||||
BLE_SUPP_CMD_LE_SET_RESV_ADDR_TMO | \
|
||||
BLE_SUPP_CMD_LE_RD_MAX_DATALEN | \
|
||||
BLE_SUPP_CMD_LE_READ_PHY | \
|
||||
BLE_SUPP_CMD_LE_SET_DEFAULT_PHY | \
|
||||
BLE_SUPP_CMD_LE_SET_PHY | \
|
||||
BLE_SUPP_CMD_LE_ENHANCED_RX_TEST \
|
||||
)
|
||||
|
||||
/* Octet 36 */
|
||||
#if MYNEWT_VAL(BLE_LL_DTM)
|
||||
#define BLE_SUPP_CMD_LE_ENHANCED_TX_TEST (1 << 0)
|
||||
#else
|
||||
#define BLE_SUPP_CMD_LE_ENHANCED_TX_TEST (0 << 0)
|
||||
#endif
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
|
||||
#define BLE_SUPP_CMD_LE_SET_ADVS_RAND_ADDR (1 << 1)
|
||||
#define BLE_SUPP_CMD_LE_SET_EXT_ADV_PARAM (1 << 2)
|
||||
#define BLE_SUPP_CMD_LE_SET_EXT_ADV_DATA (1 << 3)
|
||||
#define BLE_SUPP_CMD_LE_SET_EXT_SCAN_RSP (1 << 4)
|
||||
#define BLE_SUPP_CMD_LE_SET_EXT_ADV_ENABLE (1 << 5)
|
||||
#define BLE_SUPP_CMD_LE_RD_MAX_ADV_DATA_LEN (1 << 6)
|
||||
#define BLE_SUPP_CMD_LE_RD_NUM_SUPP_ADVS (1 << 7)
|
||||
#else
|
||||
#define BLE_SUPP_CMD_LE_SET_ADVS_RAND_ADDR (0 << 1)
|
||||
#define BLE_SUPP_CMD_LE_SET_EXT_ADV_PARAM (0 << 2)
|
||||
#define BLE_SUPP_CMD_LE_SET_EXT_ADV_DATA (0 << 3)
|
||||
#define BLE_SUPP_CMD_LE_SET_EXT_SCAN_RSP (0 << 4)
|
||||
#define BLE_SUPP_CMD_LE_SET_EXT_ADV_ENABLE (0 << 5)
|
||||
#define BLE_SUPP_CMD_LE_RD_MAX_ADV_DATA_LEN (0 << 6)
|
||||
#define BLE_SUPP_CMD_LE_RD_NUM_SUPP_ADVS (0 << 7)
|
||||
#endif
|
||||
|
||||
#define BLE_LL_SUPP_CMD_OCTET_36 \
|
||||
( \
|
||||
BLE_SUPP_CMD_LE_ENHANCED_TX_TEST | \
|
||||
BLE_SUPP_CMD_LE_SET_ADVS_RAND_ADDR | \
|
||||
BLE_SUPP_CMD_LE_SET_EXT_ADV_PARAM | \
|
||||
BLE_SUPP_CMD_LE_SET_EXT_ADV_DATA | \
|
||||
BLE_SUPP_CMD_LE_SET_EXT_SCAN_RSP | \
|
||||
BLE_SUPP_CMD_LE_SET_EXT_ADV_ENABLE | \
|
||||
BLE_SUPP_CMD_LE_RD_MAX_ADV_DATA_LEN | \
|
||||
BLE_SUPP_CMD_LE_RD_NUM_SUPP_ADVS \
|
||||
)
|
||||
|
||||
/* Octet 37 */
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
|
||||
#define BLE_SUPP_CMD_LE_REMOVE_ADVS (1 << 0)
|
||||
#define BLE_SUPP_CMD_LE_CLEAR_ADVS (1 << 1)
|
||||
#else
|
||||
#define BLE_SUPP_CMD_LE_REMOVE_ADVS (0 << 0)
|
||||
#define BLE_SUPP_CMD_LE_CLEAR_ADVS (0 << 1)
|
||||
#endif
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV)
|
||||
#define BLE_SUPP_CMD_LE_SET_PADV_PARAM (1 << 2)
|
||||
#define BLE_SUPP_CMD_LE_SET_PADV_DATA (1 << 3)
|
||||
#define BLE_SUPP_CMD_LE_SET_PADV_ENABLE (1 << 4)
|
||||
#else
|
||||
#define BLE_SUPP_CMD_LE_SET_PADV_PARAM (0 << 2)
|
||||
#define BLE_SUPP_CMD_LE_SET_PADV_DATA (0 << 3)
|
||||
#define BLE_SUPP_CMD_LE_SET_PADV_ENABLE (0 << 4)
|
||||
#endif
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_EXT_ADV)
|
||||
#define BLE_SUPP_CMD_LE_SET_EXT_SCAN_PARAM (1 << 5)
|
||||
#define BLE_SUPP_CMD_LE_SET_EXT_SCAN_ENABLE (1 << 6)
|
||||
#define BLE_SUPP_CMD_LE_EXT_CREATE_CONN (1 << 7)
|
||||
#else
|
||||
#define BLE_SUPP_CMD_LE_SET_EXT_SCAN_PARAM (0 << 5)
|
||||
#define BLE_SUPP_CMD_LE_SET_EXT_SCAN_ENABLE (0 << 6)
|
||||
#define BLE_SUPP_CMD_LE_EXT_CREATE_CONN (0 << 7)
|
||||
#endif
|
||||
|
||||
#define BLE_LL_SUPP_CMD_OCTET_37 \
|
||||
( \
|
||||
BLE_SUPP_CMD_LE_REMOVE_ADVS | \
|
||||
BLE_SUPP_CMD_LE_CLEAR_ADVS | \
|
||||
BLE_SUPP_CMD_LE_SET_PADV_PARAM | \
|
||||
BLE_SUPP_CMD_LE_SET_PADV_DATA | \
|
||||
BLE_SUPP_CMD_LE_SET_PADV_ENABLE | \
|
||||
BLE_SUPP_CMD_LE_SET_EXT_SCAN_PARAM | \
|
||||
BLE_SUPP_CMD_LE_SET_EXT_SCAN_ENABLE | \
|
||||
BLE_SUPP_CMD_LE_EXT_CREATE_CONN \
|
||||
)
|
||||
|
||||
/* Octet 38 */
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV)
|
||||
#define BLE_SUPP_CMD_LE_PADV_CREATE_SYNC (1 << 0)
|
||||
#define BLE_SUPP_CMD_LE_PADV_CREATE_SYNC_C (1 << 1)
|
||||
#define BLE_SUPP_CMD_LE_PADV_TERMINATE_SYNC (1 << 2)
|
||||
#define BLE_SUPP_CMD_LE_ADD_PADV_LIST (1 << 3)
|
||||
#define BLE_SUPP_CMD_LE_REMOVE_PADV_LIST (1 << 4)
|
||||
#define BLE_SUPP_CMD_LE_CLEAR_PADV_LIST (1 << 5)
|
||||
#define BLE_SUPP_CMD_LE_RD_PADV_LIST_SIZE (1 << 6)
|
||||
#else
|
||||
#define BLE_SUPP_CMD_LE_PADV_CREATE_SYNC (0 << 0)
|
||||
#define BLE_SUPP_CMD_LE_PADV_CREATE_SYNC_C (0 << 1)
|
||||
#define BLE_SUPP_CMD_LE_PADV_TERMINATE_SYNC (0 << 2)
|
||||
#define BLE_SUPP_CMD_LE_ADD_PADV_LIST (0 << 3)
|
||||
#define BLE_SUPP_CMD_LE_REMOVE_PADV_LIST (0 << 4)
|
||||
#define BLE_SUPP_CMD_LE_CLEAR_PADV_LIST (0 << 5)
|
||||
#define BLE_SUPP_CMD_LE_RD_PADV_LIST_SIZE (0 << 6)
|
||||
#endif
|
||||
#define BLE_SUPP_CMD_LE_RD_TX_POWER (1 << 7)
|
||||
|
||||
#define BLE_LL_SUPP_CMD_OCTET_38 \
|
||||
( \
|
||||
BLE_SUPP_CMD_LE_PADV_CREATE_SYNC | \
|
||||
BLE_SUPP_CMD_LE_PADV_CREATE_SYNC_C | \
|
||||
BLE_SUPP_CMD_LE_PADV_TERMINATE_SYNC | \
|
||||
BLE_SUPP_CMD_LE_ADD_PADV_LIST | \
|
||||
BLE_SUPP_CMD_LE_REMOVE_PADV_LIST | \
|
||||
BLE_SUPP_CMD_LE_CLEAR_PADV_LIST | \
|
||||
BLE_SUPP_CMD_LE_RD_PADV_LIST_SIZE | \
|
||||
BLE_SUPP_CMD_LE_RD_TX_POWER \
|
||||
)
|
||||
|
||||
/* Octet 39 */
|
||||
#define BLE_SUPP_CMD_LE_RD_RF_PATH_COMP (1 << 0)
|
||||
#define BLE_SUPP_CMD_LE_WR_RF_PATH_COMP (1 << 1)
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
|
||||
#define BLE_SUPP_CMD_LE_SET_PRIVACY_MODE (1 << 2)
|
||||
#else
|
||||
#define BLE_SUPP_CMD_LE_SET_PRIVACY_MODE (0 << 2)
|
||||
#endif
|
||||
|
||||
#define BLE_LL_SUPP_CMD_OCTET_39 \
|
||||
( \
|
||||
BLE_SUPP_CMD_LE_RD_RF_PATH_COMP | \
|
||||
BLE_SUPP_CMD_LE_WR_RF_PATH_COMP | \
|
||||
BLE_SUPP_CMD_LE_SET_PRIVACY_MODE \
|
||||
)
|
||||
|
||||
/* Octet 40 */
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV) && MYNEWT_VAL(BLE_VERSION) >= 51
|
||||
#define BLE_SUPP_CMD_LE_PADV_RECV_ENABLE (1 << 5)
|
||||
#else
|
||||
#define BLE_SUPP_CMD_LE_PADV_RECV_ENABLE (0 << 5)
|
||||
#endif
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER)
|
||||
#define BLE_SUPP_CMD_LE_PADV_SYNC_TRANSFER (1 << 6)
|
||||
#define BLE_SUPP_CMD_LE_PADV_SET_INFO_TRANSFER (1 << 7)
|
||||
#else
|
||||
#define BLE_SUPP_CMD_LE_PADV_SYNC_TRANSFER (0 << 6)
|
||||
#define BLE_SUPP_CMD_LE_PADV_SET_INFO_TRANSFER (0 << 7)
|
||||
#endif
|
||||
|
||||
#define BLE_LL_SUPP_CMD_OCTET_40 \
|
||||
( \
|
||||
BLE_SUPP_CMD_LE_PADV_RECV_ENABLE | \
|
||||
BLE_SUPP_CMD_LE_PADV_SYNC_TRANSFER | \
|
||||
BLE_SUPP_CMD_LE_PADV_SET_INFO_TRANSFER \
|
||||
)
|
||||
|
||||
/* Octet 41 */
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PERIODIC_ADV_SYNC_TRANSFER)
|
||||
#define BLE_SUPP_CMD_LE_PADV_SYNC_TRANSFER_PARAMS (1 << 0)
|
||||
#define BLE_SUPP_CMD_LE_PADV_DEFAULT_SYNC_TRANSFER_PARAMS (1 << 1)
|
||||
#else
|
||||
#define BLE_SUPP_CMD_LE_PADV_SYNC_TRANSFER_PARAMS (0 << 0)
|
||||
#define BLE_SUPP_CMD_LE_PADV_DEFAULT_SYNC_TRANSFER_PARAMS (0 << 1)
|
||||
#endif
|
||||
#define BLE_LL_SUPP_CMD_OCTET_41 \
|
||||
( \
|
||||
BLE_SUPP_CMD_LE_PADV_SYNC_TRANSFER_PARAMS | \
|
||||
BLE_SUPP_CMD_LE_PADV_DEFAULT_SYNC_TRANSFER_PARAMS \
|
||||
)
|
||||
|
||||
/* Defines the array of supported commands */
|
||||
const uint8_t g_ble_ll_supp_cmds[BLE_LL_SUPP_CMD_LEN] =
|
||||
{
|
||||
BLE_LL_SUPP_CMD_OCTET_0, /* Octet 0 */
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
BLE_LL_SUPP_CMD_OCTET_5,
|
||||
0,
|
||||
0,
|
||||
0, /* Octet 8 */
|
||||
0,
|
||||
BLE_LL_SUPP_CMD_OCTET_10,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
BLE_LL_SUPP_CMD_OCTET_14,
|
||||
BLE_LL_SUPP_CMD_OCTET_15,
|
||||
0, /* Octet 16 */
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0, /* Octet 24 */
|
||||
BLE_LL_SUPP_CMD_OCTET_25,
|
||||
BLE_LL_SUPP_CMD_OCTET_26,
|
||||
BLE_LL_SUPP_CMD_OCTET_27,
|
||||
BLE_LL_SUPP_CMD_OCTET_28,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0, /* Octet 32 */
|
||||
BLE_LL_SUPP_CMD_OCTET_33,
|
||||
BLE_LL_SUPP_CMD_OCTET_34,
|
||||
BLE_LL_SUPP_CMD_OCTET_35,
|
||||
BLE_LL_SUPP_CMD_OCTET_36,
|
||||
BLE_LL_SUPP_CMD_OCTET_37,
|
||||
BLE_LL_SUPP_CMD_OCTET_38,
|
||||
BLE_LL_SUPP_CMD_OCTET_39,
|
||||
BLE_LL_SUPP_CMD_OCTET_40, /* Octet 40 */
|
||||
BLE_LL_SUPP_CMD_OCTET_41,
|
||||
};
|
||||
|
||||
#endif
|
||||
2248
lib/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_sync.c
Normal file
2248
lib/NimBLE-Arduino/src/nimble/nimble/controller/src/ble_ll_sync.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
#ifndef ESP_PLATFORM
|
||||
#include <stdint.h>
|
||||
#include "nimble/porting/nimble/include/syscfg/syscfg.h"
|
||||
#include "nimble/porting/nimble/include/os/os_trace_api.h"
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_SYSVIEW)
|
||||
|
||||
static os_trace_module_t g_ble_ll_trace_mod;
|
||||
uint32_t ble_ll_trace_off;
|
||||
|
||||
static void
|
||||
ble_ll_trace_module_send_desc(void)
|
||||
{
|
||||
os_trace_module_desc(&g_ble_ll_trace_mod, "0 ll_sched lls=%u cputime=%u start_time=%u");
|
||||
os_trace_module_desc(&g_ble_ll_trace_mod, "1 ll_rx_start lls=%u pdu_type=%x");
|
||||
os_trace_module_desc(&g_ble_ll_trace_mod, "2 ll_rx_end pdu_type=%x len=%u flags=%x");
|
||||
os_trace_module_desc(&g_ble_ll_trace_mod, "3 ll_wfr_timer_exp lls=%u xcvr=%u rx_start=%u");
|
||||
os_trace_module_desc(&g_ble_ll_trace_mod, "4 ll_ctrl_rx opcode=%u len=%u");
|
||||
os_trace_module_desc(&g_ble_ll_trace_mod, "5 ll_conn_ev_start conn_handle=%u");
|
||||
os_trace_module_desc(&g_ble_ll_trace_mod, "6 ll_conn_ev_end conn_handle=%u event_cntr=%u");
|
||||
os_trace_module_desc(&g_ble_ll_trace_mod, "7 ll_conn_end conn_handle=%u event_cntr=%u err=%u");
|
||||
os_trace_module_desc(&g_ble_ll_trace_mod, "8 ll_conn_tx len=%u offset=%u");
|
||||
os_trace_module_desc(&g_ble_ll_trace_mod, "9 ll_conn_rx conn_sn=%u pdu_nesn=%u");
|
||||
os_trace_module_desc(&g_ble_ll_trace_mod, "10 ll_adv_txdone inst=%u chanset=%x");
|
||||
os_trace_module_desc(&g_ble_ll_trace_mod, "11 ll_adv_halt inst=%u");
|
||||
os_trace_module_desc(&g_ble_ll_trace_mod, "12 ll_aux_ref aux=%p ref=%u");
|
||||
os_trace_module_desc(&g_ble_ll_trace_mod, "13 ll_aux_unref aux=%p ref=%u");
|
||||
}
|
||||
|
||||
void
|
||||
ble_ll_trace_init(void)
|
||||
{
|
||||
ble_ll_trace_off =
|
||||
os_trace_module_register(&g_ble_ll_trace_mod, "ble_ll", 12,
|
||||
ble_ll_trace_module_send_desc);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@@ -0,0 +1,303 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
#ifndef ESP_PLATFORM
|
||||
|
||||
#include <assert.h>
|
||||
#include <stdlib.h>
|
||||
#include "nimble/nimble/include/nimble/ble.h"
|
||||
#include "../include/controller/ble_ll.h"
|
||||
#include "../include/controller/ble_ll_utils.h"
|
||||
|
||||
/* 37 bits require 5 bytes */
|
||||
#define BLE_LL_CHMAP_LEN (5)
|
||||
|
||||
/* Sleep clock accuracy table (in ppm) */
|
||||
static const uint16_t g_ble_sca_ppm_tbl[8] = {
|
||||
500, 250, 150, 100, 75, 50, 30, 20
|
||||
};
|
||||
|
||||
uint32_t
|
||||
ble_ll_utils_calc_access_addr(void)
|
||||
{
|
||||
uint32_t aa;
|
||||
uint16_t aa_low;
|
||||
uint16_t aa_high;
|
||||
uint32_t temp;
|
||||
uint32_t mask;
|
||||
uint32_t prev_bit;
|
||||
uint8_t bits_diff;
|
||||
uint8_t consecutive;
|
||||
uint8_t transitions;
|
||||
uint8_t ones;
|
||||
int tmp;
|
||||
|
||||
/* Calculate a random access address */
|
||||
aa = 0;
|
||||
while (1) {
|
||||
/* Get two, 16-bit random numbers */
|
||||
aa_low = rand() & 0xFFFF;
|
||||
aa_high = rand() & 0xFFFF;
|
||||
|
||||
/* All four bytes cannot be equal */
|
||||
if (aa_low == aa_high) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Upper 6 bits must have 2 transitions */
|
||||
tmp = (int16_t)aa_high >> 10;
|
||||
if (__builtin_popcount(tmp ^ (tmp >> 1)) < 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Cannot be access address or be 1 bit different */
|
||||
aa = aa_high;
|
||||
aa = (aa << 16) | aa_low;
|
||||
bits_diff = 0;
|
||||
temp = aa ^ BLE_ACCESS_ADDR_ADV;
|
||||
for (mask = 0x00000001; mask != 0; mask <<= 1) {
|
||||
if (mask & temp) {
|
||||
++bits_diff;
|
||||
if (bits_diff > 1) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (bits_diff <= 1) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Cannot have more than 24 transitions */
|
||||
transitions = 0;
|
||||
consecutive = 1;
|
||||
ones = 0;
|
||||
mask = 0x00000001;
|
||||
while (mask < 0x80000000) {
|
||||
prev_bit = aa & mask;
|
||||
mask <<= 1;
|
||||
if (mask & aa) {
|
||||
if (prev_bit == 0) {
|
||||
++transitions;
|
||||
consecutive = 1;
|
||||
} else {
|
||||
++consecutive;
|
||||
}
|
||||
} else {
|
||||
if (prev_bit == 0) {
|
||||
++consecutive;
|
||||
} else {
|
||||
++transitions;
|
||||
consecutive = 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (prev_bit) {
|
||||
ones++;
|
||||
}
|
||||
|
||||
/* 8 lsb should have at least three 1 */
|
||||
if (mask == 0x00000100 && ones < 3) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* 16 lsb should have no more than 11 transitions */
|
||||
if (mask == 0x00010000 && transitions > 11) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* This is invalid! */
|
||||
if (consecutive > 6) {
|
||||
/* Make sure we always detect invalid sequence below */
|
||||
mask = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Invalid sequence found */
|
||||
if (mask != 0x80000000) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* Cannot be more than 24 transitions */
|
||||
if (transitions > 24) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* We have a valid access address */
|
||||
break;
|
||||
}
|
||||
return aa;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
ble_ll_utils_remapped_channel(uint8_t remap_index, const uint8_t *chanmap)
|
||||
{
|
||||
uint8_t cntr;
|
||||
uint8_t mask;
|
||||
uint8_t usable_chans;
|
||||
uint8_t chan;
|
||||
int i, j;
|
||||
|
||||
/* NOTE: possible to build a map but this would use memory. For now,
|
||||
* we just calculate
|
||||
* Iterate through channel map to find this channel
|
||||
*/
|
||||
chan = 0;
|
||||
cntr = 0;
|
||||
for (i = 0; i < BLE_LL_CHMAP_LEN; i++) {
|
||||
usable_chans = chanmap[i];
|
||||
if (usable_chans != 0) {
|
||||
mask = 0x01;
|
||||
for (j = 0; j < 8; j++) {
|
||||
if (usable_chans & mask) {
|
||||
if (cntr == remap_index) {
|
||||
return (chan + j);
|
||||
}
|
||||
++cntr;
|
||||
}
|
||||
mask <<= 1;
|
||||
}
|
||||
}
|
||||
chan += 8;
|
||||
}
|
||||
|
||||
/* we should never reach here */
|
||||
BLE_LL_ASSERT(0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
ble_ll_utils_calc_num_used_chans(const uint8_t *chmap)
|
||||
{
|
||||
int i;
|
||||
int j;
|
||||
uint8_t mask;
|
||||
uint8_t chanbyte;
|
||||
uint8_t used_channels;
|
||||
|
||||
used_channels = 0;
|
||||
for (i = 0; i < BLE_LL_CHMAP_LEN; ++i) {
|
||||
chanbyte = chmap[i];
|
||||
if (chanbyte) {
|
||||
if (chanbyte == 0xff) {
|
||||
used_channels += 8;
|
||||
} else {
|
||||
mask = 0x01;
|
||||
for (j = 0; j < 8; ++j) {
|
||||
if (chanbyte & mask) {
|
||||
++used_channels;
|
||||
}
|
||||
mask <<= 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return used_channels;
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LE_CSA2)
|
||||
static uint16_t
|
||||
ble_ll_utils_csa2_perm(uint16_t in)
|
||||
{
|
||||
uint16_t out = 0;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < 8; i++) {
|
||||
out |= ((in >> i) & 0x00000001) << (7 - i);
|
||||
}
|
||||
|
||||
for (i = 8; i < 16; i++) {
|
||||
out |= ((in >> i) & 0x00000001) << (15 + 8 - i);
|
||||
}
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
static uint16_t
|
||||
ble_ll_utils_csa2_prng(uint16_t counter, uint16_t ch_id)
|
||||
{
|
||||
uint16_t prn_e;
|
||||
|
||||
prn_e = counter ^ ch_id;
|
||||
|
||||
prn_e = ble_ll_utils_csa2_perm(prn_e);
|
||||
prn_e = (prn_e * 17) + ch_id;
|
||||
|
||||
prn_e = ble_ll_utils_csa2_perm(prn_e);
|
||||
prn_e = (prn_e * 17) + ch_id;
|
||||
|
||||
prn_e = ble_ll_utils_csa2_perm(prn_e);
|
||||
prn_e = (prn_e * 17) + ch_id;
|
||||
|
||||
prn_e = prn_e ^ ch_id;
|
||||
|
||||
return prn_e;
|
||||
}
|
||||
|
||||
uint8_t
|
||||
ble_ll_utils_calc_dci_csa2(uint16_t event_cntr, uint16_t channel_id,
|
||||
uint8_t num_used_chans, const uint8_t *chanmap)
|
||||
{
|
||||
uint16_t channel_unmapped;
|
||||
uint8_t remap_index;
|
||||
|
||||
uint16_t prn_e;
|
||||
uint8_t bitpos;
|
||||
|
||||
prn_e = ble_ll_utils_csa2_prng(event_cntr, channel_id);
|
||||
|
||||
channel_unmapped = prn_e % 37;
|
||||
|
||||
/*
|
||||
* If unmapped channel is the channel index of a used channel it is used
|
||||
* as channel index.
|
||||
*/
|
||||
bitpos = 1 << (channel_unmapped & 0x07);
|
||||
if (chanmap[channel_unmapped >> 3] & bitpos) {
|
||||
return channel_unmapped;
|
||||
}
|
||||
|
||||
remap_index = (num_used_chans * prn_e) / 0x10000;
|
||||
|
||||
return ble_ll_utils_remapped_channel(remap_index, chanmap);
|
||||
}
|
||||
#endif
|
||||
|
||||
uint32_t
|
||||
ble_ll_utils_calc_window_widening(uint32_t anchor_point,
|
||||
uint32_t last_anchor_point,
|
||||
uint8_t master_sca)
|
||||
{
|
||||
uint32_t total_sca_ppm;
|
||||
uint32_t window_widening;
|
||||
int32_t time_since_last_anchor;
|
||||
uint32_t delta_msec;
|
||||
|
||||
window_widening = 0;
|
||||
|
||||
time_since_last_anchor = (int32_t)(anchor_point - last_anchor_point);
|
||||
if (time_since_last_anchor > 0) {
|
||||
delta_msec = os_cputime_ticks_to_usecs(time_since_last_anchor) / 1000;
|
||||
total_sca_ppm = g_ble_sca_ppm_tbl[master_sca] +
|
||||
MYNEWT_VAL(BLE_LL_OUR_SCA);
|
||||
window_widening = (total_sca_ppm * delta_msec) / 1000;
|
||||
}
|
||||
|
||||
return window_widening;
|
||||
}
|
||||
#endif
|
||||
@@ -0,0 +1,297 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
#ifndef ESP_PLATFORM
|
||||
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "nimble/porting/nimble/include/syscfg/syscfg.h"
|
||||
#include "nimble/porting/nimble/include/os/os.h"
|
||||
#include "nimble/nimble/include/nimble/ble.h"
|
||||
#include "nimble/nimble/include/nimble/nimble_opt.h"
|
||||
|
||||
#if defined(ARDUINO_ARCH_NRF5) && defined(NRF51)
|
||||
#include "nimble/nimble/drivers/nrf51/include/ble/xcvr.h"
|
||||
#elif defined(ARDUINO_ARCH_NRF5) && defined(NRF52_SERIES)
|
||||
#include "nimble/nimble/drivers/nrf52/include/ble/xcvr.h"
|
||||
#endif
|
||||
|
||||
#include "../include/controller/ble_ll_whitelist.h"
|
||||
#include "../include/controller/ble_ll_hci.h"
|
||||
#include "../include/controller/ble_ll_adv.h"
|
||||
#include "../include/controller/ble_ll_scan.h"
|
||||
#include "../include/controller/ble_hw.h"
|
||||
|
||||
#if (MYNEWT_VAL(BLE_LL_WHITELIST_SIZE) < BLE_HW_WHITE_LIST_SIZE)
|
||||
#define BLE_LL_WHITELIST_SIZE MYNEWT_VAL(BLE_LL_WHITELIST_SIZE)
|
||||
#else
|
||||
#define BLE_LL_WHITELIST_SIZE BLE_HW_WHITE_LIST_SIZE
|
||||
#endif
|
||||
|
||||
struct ble_ll_whitelist_entry
|
||||
{
|
||||
uint8_t wl_valid;
|
||||
uint8_t wl_addr_type;
|
||||
uint8_t wl_dev_addr[BLE_DEV_ADDR_LEN];
|
||||
};
|
||||
|
||||
struct ble_ll_whitelist_entry g_ble_ll_whitelist[BLE_LL_WHITELIST_SIZE];
|
||||
|
||||
static int
|
||||
ble_ll_whitelist_chg_allowed(void)
|
||||
{
|
||||
int rc;
|
||||
|
||||
/*
|
||||
* This command is not allowed if:
|
||||
* -> advertising uses the whitelist and we are currently advertising.
|
||||
* -> scanning uses the whitelist and is enabled.
|
||||
* -> initiating uses whitelist and a LE create connection command is in
|
||||
* progress
|
||||
*/
|
||||
rc = 1;
|
||||
if (!ble_ll_adv_can_chg_whitelist() || !ble_ll_scan_can_chg_whitelist()) {
|
||||
rc = 0;
|
||||
}
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the whitelist.
|
||||
*
|
||||
* @return int 0: success, BLE error code otherwise
|
||||
*/
|
||||
int
|
||||
ble_ll_whitelist_clear(void)
|
||||
{
|
||||
int i;
|
||||
struct ble_ll_whitelist_entry *wl;
|
||||
|
||||
/* Check proper state */
|
||||
if (!ble_ll_whitelist_chg_allowed()) {
|
||||
return BLE_ERR_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
/* Set the number of entries to 0 */
|
||||
wl = &g_ble_ll_whitelist[0];
|
||||
for (i = 0; i < BLE_LL_WHITELIST_SIZE; ++i) {
|
||||
wl->wl_valid = 0;
|
||||
++wl;
|
||||
}
|
||||
|
||||
#if (BLE_USES_HW_WHITELIST == 1)
|
||||
ble_hw_whitelist_clear();
|
||||
#endif
|
||||
|
||||
return BLE_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the size of the whitelist. This is the total number of whitelist
|
||||
* entries allowed by the controller.
|
||||
*
|
||||
* @param rspbuf Pointer to response buffer
|
||||
*
|
||||
* @return int 0: success.
|
||||
*/
|
||||
int
|
||||
ble_ll_whitelist_read_size(uint8_t *rspbuf, uint8_t *rsplen)
|
||||
{
|
||||
struct ble_hci_le_rd_white_list_rp *rsp = (void *) rspbuf;
|
||||
|
||||
rsp->size = BLE_LL_WHITELIST_SIZE;
|
||||
|
||||
*rsplen = sizeof(*rsp);
|
||||
|
||||
return BLE_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches the whitelist to determine if the address is present in the
|
||||
* whitelist. This is an internal API that only searches the link layer
|
||||
* whitelist and does not care about the hardware whitelist
|
||||
*
|
||||
* @param addr Device or identity address to check.
|
||||
* @param addr_type Public address (0) or random address (1)
|
||||
*
|
||||
* @return int 0: device is not on whitelist; otherwise the return value
|
||||
* is the 'position' of the device in the whitelist (the index of the element
|
||||
* plus 1).
|
||||
*/
|
||||
static int
|
||||
ble_ll_whitelist_search(const uint8_t *addr, uint8_t addr_type)
|
||||
{
|
||||
int i;
|
||||
struct ble_ll_whitelist_entry *wl;
|
||||
|
||||
wl = &g_ble_ll_whitelist[0];
|
||||
for (i = 0; i < BLE_LL_WHITELIST_SIZE; ++i) {
|
||||
if ((wl->wl_valid) && (wl->wl_addr_type == addr_type) &&
|
||||
(!memcmp(&wl->wl_dev_addr[0], addr, BLE_DEV_ADDR_LEN))) {
|
||||
return i + 1;
|
||||
}
|
||||
++wl;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is there a match between the device and a device on the whitelist.
|
||||
*
|
||||
* NOTE: This API uses the HW, if present, to determine if there was a match
|
||||
* between a received address and an address in the whitelist. If the HW does
|
||||
* not support whitelisting this API is the same as the whitelist search API
|
||||
*
|
||||
* @param addr
|
||||
* @param addr_type Public address (0) or random address (1)
|
||||
* @param is_ident True if addr is an identity address; false otherwise
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int
|
||||
ble_ll_whitelist_match(uint8_t *addr, uint8_t addr_type, int is_ident)
|
||||
{
|
||||
int rc;
|
||||
#if (BLE_USES_HW_WHITELIST == 1)
|
||||
/*
|
||||
* XXX: This should be changed. This is HW specific: some HW may be able
|
||||
* to both resolve a private address and perform a whitelist check. The
|
||||
* current BLE hw cannot support this.
|
||||
*/
|
||||
if (is_ident) {
|
||||
rc = ble_ll_whitelist_search(addr, addr_type);
|
||||
} else {
|
||||
rc = ble_hw_whitelist_match();
|
||||
}
|
||||
#else
|
||||
rc = ble_ll_whitelist_search(addr, addr_type);
|
||||
#endif
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a device to the whitelist
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int
|
||||
ble_ll_whitelist_add(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
const struct ble_hci_le_add_whte_list_cp *cmd = (const void *) cmdbuf;
|
||||
struct ble_ll_whitelist_entry *wl;
|
||||
int rc;
|
||||
int i;
|
||||
|
||||
if (len != sizeof(*cmd)) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
/* Must be in proper state */
|
||||
if (!ble_ll_whitelist_chg_allowed()) {
|
||||
return BLE_ERR_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
/* Check if we have any open entries */
|
||||
rc = BLE_ERR_SUCCESS;
|
||||
if (!ble_ll_whitelist_search(cmd->addr, cmd->addr_type)) {
|
||||
wl = &g_ble_ll_whitelist[0];
|
||||
for (i = 0; i < BLE_LL_WHITELIST_SIZE; ++i) {
|
||||
if (wl->wl_valid == 0) {
|
||||
memcpy(&wl->wl_dev_addr[0], cmd->addr, BLE_DEV_ADDR_LEN);
|
||||
wl->wl_addr_type = cmd->addr_type;
|
||||
wl->wl_valid = 1;
|
||||
break;
|
||||
}
|
||||
++wl;
|
||||
}
|
||||
|
||||
if (i == BLE_LL_WHITELIST_SIZE) {
|
||||
rc = BLE_ERR_MEM_CAPACITY;
|
||||
} else {
|
||||
#if (BLE_USES_HW_WHITELIST == 1)
|
||||
rc = ble_hw_whitelist_add(cmd->addr, cmd->addr_type);
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a device from the whitelist
|
||||
*
|
||||
* @param cmdbuf
|
||||
*
|
||||
* @return int 0: success, BLE error code otherwise
|
||||
*/
|
||||
int
|
||||
ble_ll_whitelist_rmv(const uint8_t *cmdbuf, uint8_t len)
|
||||
{
|
||||
const struct ble_hci_le_rmv_white_list_cp *cmd = (const void *) cmdbuf;
|
||||
int position;
|
||||
|
||||
if (len != sizeof(*cmd)) {
|
||||
return BLE_ERR_INV_HCI_CMD_PARMS;
|
||||
}
|
||||
|
||||
/* Must be in proper state */
|
||||
if (!ble_ll_whitelist_chg_allowed()) {
|
||||
return BLE_ERR_CMD_DISALLOWED;
|
||||
}
|
||||
|
||||
position = ble_ll_whitelist_search(cmd->addr, cmd->addr_type);
|
||||
if (position) {
|
||||
g_ble_ll_whitelist[position - 1].wl_valid = 0;
|
||||
}
|
||||
|
||||
#if (BLE_USES_HW_WHITELIST == 1)
|
||||
ble_hw_whitelist_rmv(cmd->addr, cmd->addr_type);
|
||||
#endif
|
||||
|
||||
return BLE_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable whitelisting.
|
||||
*
|
||||
* Note: This function has no effect if we are not using HW whitelisting
|
||||
*/
|
||||
void
|
||||
ble_ll_whitelist_enable(void)
|
||||
{
|
||||
#if (BLE_USES_HW_WHITELIST == 1)
|
||||
ble_hw_whitelist_enable();
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* Disable whitelisting.
|
||||
*
|
||||
* Note: This function has no effect if we are not using HW whitelisting
|
||||
*/
|
||||
void
|
||||
ble_ll_whitelist_disable(void)
|
||||
{
|
||||
#if (BLE_USES_HW_WHITELIST == 1)
|
||||
ble_hw_whitelist_disable();
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#if defined(ARDUINO_ARCH_NRF5) && defined(NRF51)
|
||||
|
||||
#ifndef H_BLE_XCVR_
|
||||
#define H_BLE_XCVR_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Transceiver specific defintions */
|
||||
/* NOTE: we have to account for the RTC output compare issue */
|
||||
#define XCVR_PROC_DELAY_USECS (230)
|
||||
|
||||
#define XCVR_RX_START_DELAY_USECS (140)
|
||||
#define XCVR_TX_START_DELAY_USECS (140)
|
||||
#define XCVR_TX_SCHED_DELAY_USECS \
|
||||
(XCVR_TX_START_DELAY_USECS + XCVR_PROC_DELAY_USECS)
|
||||
#define XCVR_RX_SCHED_DELAY_USECS \
|
||||
(XCVR_RX_START_DELAY_USECS + XCVR_PROC_DELAY_USECS)
|
||||
|
||||
/*
|
||||
* Define HW whitelist size. This is the total possible whitelist size;
|
||||
* not necessarily the size that will be used (may be smaller)
|
||||
*/
|
||||
#define BLE_HW_WHITE_LIST_SIZE (8)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* H_BLE_XCVR_ */
|
||||
#endif
|
||||
491
lib/NimBLE-Arduino/src/nimble/nimble/drivers/nrf51/src/ble_hw.c
Normal file
491
lib/NimBLE-Arduino/src/nimble/nimble/drivers/nrf51/src/ble_hw.c
Normal file
@@ -0,0 +1,491 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#if defined(ARDUINO_ARCH_NRF5) && defined(NRF51)
|
||||
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "nimble/porting/nimble/include/syscfg/syscfg.h"
|
||||
#include "nimble/porting/nimble/include/os/os.h"
|
||||
#include "../include/ble/xcvr.h"
|
||||
#include "nimble/nimble/include/nimble/ble.h"
|
||||
#include "nimble/nimble/include/nimble/nimble_opt.h"
|
||||
#include "nrf.h"
|
||||
#include "nimble/nimble/controller/include/controller/ble_hw.h"
|
||||
#if MYNEWT
|
||||
#include "mcu/cmsis_nvic.h"
|
||||
#else
|
||||
#include "core_cm0.h"
|
||||
#include "nimble/porting/npl/freertos/include/nimble/nimble_npl_os.h"
|
||||
#endif
|
||||
#include "nimble/porting/nimble/include/os/os_trace_api.h"
|
||||
|
||||
/* Total number of resolving list elements */
|
||||
#define BLE_HW_RESOLV_LIST_SIZE (16)
|
||||
|
||||
/* We use this to keep track of which entries are set to valid addresses */
|
||||
static uint8_t g_ble_hw_whitelist_mask;
|
||||
|
||||
/* Random number generator isr callback */
|
||||
ble_rng_isr_cb_t g_ble_rng_isr_cb;
|
||||
|
||||
/* If LL privacy is enabled, allocate memory for AAR */
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
|
||||
|
||||
/* The NRF51 supports up to 16 IRK entries */
|
||||
#if (MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE) < 16)
|
||||
#define NRF_IRK_LIST_ENTRIES (MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE))
|
||||
#else
|
||||
#define NRF_IRK_LIST_ENTRIES (16)
|
||||
#endif
|
||||
|
||||
/* NOTE: each entry is 16 bytes long. */
|
||||
uint32_t g_nrf_irk_list[NRF_IRK_LIST_ENTRIES * 4];
|
||||
|
||||
/* Current number of IRK entries */
|
||||
uint8_t g_nrf_num_irks;
|
||||
|
||||
#endif
|
||||
|
||||
/* Returns public device address or -1 if not present */
|
||||
int
|
||||
ble_hw_get_public_addr(ble_addr_t *addr)
|
||||
{
|
||||
uint32_t addr_high;
|
||||
uint32_t addr_low;
|
||||
|
||||
/* Does FICR have a public address */
|
||||
if ((NRF_FICR->DEVICEADDRTYPE & 1) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Copy into device address. We can do this because we know platform */
|
||||
addr_low = NRF_FICR->DEVICEADDR[0];
|
||||
addr_high = NRF_FICR->DEVICEADDR[1];
|
||||
memcpy(addr->val, &addr_low, 4);
|
||||
memcpy(&addr->val[4], &addr_high, 2);
|
||||
addr->type = BLE_ADDR_PUBLIC;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Returns random static address or -1 if not present */
|
||||
int
|
||||
ble_hw_get_static_addr(ble_addr_t *addr)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if ((NRF_FICR->DEVICEADDRTYPE & 1) == 1) {
|
||||
memcpy(addr->val, (void *)&NRF_FICR->DEVICEADDR[0], 4);
|
||||
memcpy(&addr->val[4], (void *)&NRF_FICR->DEVICEADDR[1], 2);
|
||||
addr->val[5] |= 0xc0;
|
||||
addr->type = BLE_ADDR_RANDOM;
|
||||
rc = 0;
|
||||
} else {
|
||||
rc = -1;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the whitelist
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
void
|
||||
ble_hw_whitelist_clear(void)
|
||||
{
|
||||
NRF_RADIO->DACNF = 0;
|
||||
g_ble_hw_whitelist_mask = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a device to the hw whitelist
|
||||
*
|
||||
* @param addr
|
||||
* @param addr_type
|
||||
*
|
||||
* @return int 0: success, BLE error code otherwise
|
||||
*/
|
||||
int
|
||||
ble_hw_whitelist_add(const uint8_t *addr, uint8_t addr_type)
|
||||
{
|
||||
int i;
|
||||
uint32_t mask;
|
||||
|
||||
/* Find first ununsed device address match element */
|
||||
mask = 0x01;
|
||||
for (i = 0; i < BLE_HW_WHITE_LIST_SIZE; ++i) {
|
||||
if ((mask & g_ble_hw_whitelist_mask) == 0) {
|
||||
NRF_RADIO->DAB[i] = get_le32(addr);
|
||||
NRF_RADIO->DAP[i] = get_le16(addr + 4);
|
||||
if (addr_type == BLE_ADDR_RANDOM) {
|
||||
NRF_RADIO->DACNF |= (mask << 8);
|
||||
}
|
||||
g_ble_hw_whitelist_mask |= mask;
|
||||
return BLE_ERR_SUCCESS;
|
||||
}
|
||||
mask <<= 1;
|
||||
}
|
||||
|
||||
return BLE_ERR_MEM_CAPACITY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a device from the hw whitelist
|
||||
*
|
||||
* @param addr
|
||||
* @param addr_type
|
||||
*
|
||||
*/
|
||||
void
|
||||
ble_hw_whitelist_rmv(const uint8_t *addr, uint8_t addr_type)
|
||||
{
|
||||
int i;
|
||||
uint8_t cfg_addr;
|
||||
uint16_t dap;
|
||||
uint16_t txadd;
|
||||
uint32_t dab;
|
||||
uint32_t mask;
|
||||
|
||||
/* Find first ununsed device address match element */
|
||||
dab = get_le32(addr);
|
||||
dap = get_le16(addr + 4);
|
||||
txadd = NRF_RADIO->DACNF >> 8;
|
||||
mask = 0x01;
|
||||
for (i = 0; i < BLE_HW_WHITE_LIST_SIZE; ++i) {
|
||||
if (mask & g_ble_hw_whitelist_mask) {
|
||||
if ((dab == NRF_RADIO->DAB[i]) && (dap == NRF_RADIO->DAP[i])) {
|
||||
cfg_addr = txadd & mask;
|
||||
if (addr_type == BLE_ADDR_RANDOM) {
|
||||
if (cfg_addr != 0) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (cfg_addr == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
mask <<= 1;
|
||||
}
|
||||
|
||||
if (i < BLE_HW_WHITE_LIST_SIZE) {
|
||||
g_ble_hw_whitelist_mask &= ~mask;
|
||||
NRF_RADIO->DACNF &= ~mask;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of the whitelist in HW
|
||||
*
|
||||
* @return int Number of devices allowed in whitelist
|
||||
*/
|
||||
uint8_t
|
||||
ble_hw_whitelist_size(void)
|
||||
{
|
||||
return BLE_HW_WHITE_LIST_SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable the whitelisted devices
|
||||
*/
|
||||
void
|
||||
ble_hw_whitelist_enable(void)
|
||||
{
|
||||
/* Enable the configured device addresses */
|
||||
NRF_RADIO->DACNF |= g_ble_hw_whitelist_mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables the whitelisted devices
|
||||
*/
|
||||
void
|
||||
ble_hw_whitelist_disable(void)
|
||||
{
|
||||
/* Disable all whitelist devices */
|
||||
NRF_RADIO->DACNF &= 0x0000ff00;
|
||||
}
|
||||
|
||||
/**
|
||||
* Boolean function which returns true ('1') if there is a match on the
|
||||
* whitelist.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int
|
||||
ble_hw_whitelist_match(void)
|
||||
{
|
||||
return (int)NRF_RADIO->EVENTS_DEVMATCH;
|
||||
}
|
||||
|
||||
/* Encrypt data */
|
||||
int
|
||||
ble_hw_encrypt_block(struct ble_encryption_block *ecb)
|
||||
{
|
||||
int rc;
|
||||
uint32_t end;
|
||||
uint32_t err;
|
||||
|
||||
/* Stop ECB */
|
||||
NRF_ECB->TASKS_STOPECB = 1;
|
||||
/* XXX: does task stop clear these counters? Anyway to do this quicker? */
|
||||
NRF_ECB->EVENTS_ENDECB = 0;
|
||||
NRF_ECB->EVENTS_ERRORECB = 0;
|
||||
NRF_ECB->ECBDATAPTR = (uint32_t)ecb;
|
||||
|
||||
/* Start ECB */
|
||||
NRF_ECB->TASKS_STARTECB = 1;
|
||||
|
||||
/* Wait till error or done */
|
||||
rc = 0;
|
||||
while (1) {
|
||||
end = NRF_ECB->EVENTS_ENDECB;
|
||||
err = NRF_ECB->EVENTS_ERRORECB;
|
||||
if (end || err) {
|
||||
if (err) {
|
||||
rc = -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Random number generator ISR.
|
||||
*/
|
||||
static void
|
||||
ble_rng_isr(void)
|
||||
{
|
||||
uint8_t rnum;
|
||||
|
||||
os_trace_isr_enter();
|
||||
|
||||
/* No callback? Clear and disable interrupts */
|
||||
if (g_ble_rng_isr_cb == NULL) {
|
||||
NRF_RNG->INTENCLR = 1;
|
||||
NRF_RNG->EVENTS_VALRDY = 0;
|
||||
(void)NRF_RNG->SHORTS;
|
||||
os_trace_isr_exit();
|
||||
return;
|
||||
}
|
||||
|
||||
/* If there is a value ready grab it */
|
||||
if (NRF_RNG->EVENTS_VALRDY) {
|
||||
NRF_RNG->EVENTS_VALRDY = 0;
|
||||
rnum = (uint8_t)NRF_RNG->VALUE;
|
||||
(*g_ble_rng_isr_cb)(rnum);
|
||||
}
|
||||
|
||||
os_trace_isr_exit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the random number generator
|
||||
*
|
||||
* @param cb
|
||||
* @param bias
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int
|
||||
ble_hw_rng_init(ble_rng_isr_cb_t cb, int bias)
|
||||
{
|
||||
/* Set bias */
|
||||
if (bias) {
|
||||
NRF_RNG->CONFIG = 1;
|
||||
} else {
|
||||
NRF_RNG->CONFIG = 0;
|
||||
}
|
||||
|
||||
/* If we were passed a function pointer we need to enable the interrupt */
|
||||
if (cb != NULL) {
|
||||
#ifndef RIOT_VERSION
|
||||
NVIC_SetPriority(RNG_IRQn, (1 << __NVIC_PRIO_BITS) - 1);
|
||||
#endif
|
||||
#if MYNEWT
|
||||
NVIC_SetVector(RNG_IRQn, (uint32_t)ble_rng_isr);
|
||||
#else
|
||||
ble_npl_hw_set_isr(RNG_IRQn, ble_rng_isr);
|
||||
#endif
|
||||
NVIC_EnableIRQ(RNG_IRQn);
|
||||
g_ble_rng_isr_cb = cb;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the random number generator
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int
|
||||
ble_hw_rng_start(void)
|
||||
{
|
||||
os_sr_t sr;
|
||||
|
||||
/* No need for interrupt if there is no callback */
|
||||
OS_ENTER_CRITICAL(sr);
|
||||
NRF_RNG->EVENTS_VALRDY = 0;
|
||||
if (g_ble_rng_isr_cb) {
|
||||
NRF_RNG->INTENSET = 1;
|
||||
}
|
||||
NRF_RNG->TASKS_START = 1;
|
||||
OS_EXIT_CRITICAL(sr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the random generator
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int
|
||||
ble_hw_rng_stop(void)
|
||||
{
|
||||
os_sr_t sr;
|
||||
|
||||
/* No need for interrupt if there is no callback */
|
||||
OS_ENTER_CRITICAL(sr);
|
||||
NRF_RNG->INTENCLR = 1;
|
||||
NRF_RNG->TASKS_STOP = 1;
|
||||
NRF_RNG->EVENTS_VALRDY = 0;
|
||||
OS_EXIT_CRITICAL(sr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the random number generator.
|
||||
*
|
||||
* @return uint8_t
|
||||
*/
|
||||
uint8_t
|
||||
ble_hw_rng_read(void)
|
||||
{
|
||||
uint8_t rnum;
|
||||
|
||||
/* Wait for a sample */
|
||||
while (NRF_RNG->EVENTS_VALRDY == 0) {
|
||||
}
|
||||
|
||||
NRF_RNG->EVENTS_VALRDY = 0;
|
||||
rnum = (uint8_t)NRF_RNG->VALUE;
|
||||
|
||||
return rnum;
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
|
||||
/**
|
||||
* Clear the resolving list
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
void
|
||||
ble_hw_resolv_list_clear(void)
|
||||
{
|
||||
g_nrf_num_irks = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a device to the hw resolving list
|
||||
*
|
||||
* @param irk Pointer to IRK to add
|
||||
*
|
||||
* @return int 0: success, BLE error code otherwise
|
||||
*/
|
||||
int
|
||||
ble_hw_resolv_list_add(uint8_t *irk)
|
||||
{
|
||||
uint32_t *nrf_entry;
|
||||
|
||||
/* Find first ununsed device address match element */
|
||||
if (g_nrf_num_irks == NRF_IRK_LIST_ENTRIES) {
|
||||
return BLE_ERR_MEM_CAPACITY;
|
||||
}
|
||||
|
||||
/* Copy into irk list */
|
||||
nrf_entry = &g_nrf_irk_list[4 * g_nrf_num_irks];
|
||||
memcpy(nrf_entry, irk, 16);
|
||||
|
||||
/* Add to total */
|
||||
++g_nrf_num_irks;
|
||||
return BLE_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a device from the hw resolving list
|
||||
*
|
||||
* @param index Index of IRK to remove
|
||||
*/
|
||||
void
|
||||
ble_hw_resolv_list_rmv(int index)
|
||||
{
|
||||
uint32_t *irk_entry;
|
||||
|
||||
if (index < g_nrf_num_irks) {
|
||||
--g_nrf_num_irks;
|
||||
irk_entry = &g_nrf_irk_list[index];
|
||||
if (g_nrf_num_irks > index) {
|
||||
memmove(irk_entry, irk_entry + 4, 16 * (g_nrf_num_irks - index));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of the resolving list. NOTE: this returns the maximum
|
||||
* allowable entries in the HW. Configuration options may limit this.
|
||||
*
|
||||
* @return int Number of devices allowed in resolving list
|
||||
*/
|
||||
uint8_t
|
||||
ble_hw_resolv_list_size(void)
|
||||
{
|
||||
return BLE_HW_RESOLV_LIST_SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to determine if the address received was resolved.
|
||||
*
|
||||
* @return int Negative values indicate unresolved address; positive values
|
||||
* indicate index in resolving list of resolved address.
|
||||
*/
|
||||
int
|
||||
ble_hw_resolv_list_match(void)
|
||||
{
|
||||
uint32_t index;
|
||||
|
||||
if (NRF_AAR->EVENTS_END) {
|
||||
if (NRF_AAR->EVENTS_RESOLVED) {
|
||||
index = NRF_AAR->STATUS;
|
||||
return (int)index;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
1527
lib/NimBLE-Arduino/src/nimble/nimble/drivers/nrf51/src/ble_phy.c
Normal file
1527
lib/NimBLE-Arduino/src/nimble/nimble/drivers/nrf51/src/ble_phy.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#if defined(ARDUINO_ARCH_NRF5) && defined(NRF52_SERIES)
|
||||
|
||||
#ifndef H_BLE_XCVR_
|
||||
#define H_BLE_XCVR_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define XCVR_RX_RADIO_RAMPUP_USECS (40)
|
||||
#define XCVR_TX_RADIO_RAMPUP_USECS (40)
|
||||
|
||||
/*
|
||||
* NOTE: we have to account for the RTC output compare issue. We want it to be
|
||||
* 5 ticks.
|
||||
*/
|
||||
#define XCVR_PROC_DELAY_USECS (153)
|
||||
#define XCVR_RX_START_DELAY_USECS (XCVR_RX_RADIO_RAMPUP_USECS)
|
||||
#define XCVR_TX_START_DELAY_USECS (XCVR_TX_RADIO_RAMPUP_USECS)
|
||||
#define XCVR_TX_SCHED_DELAY_USECS \
|
||||
(XCVR_TX_START_DELAY_USECS + XCVR_PROC_DELAY_USECS)
|
||||
#define XCVR_RX_SCHED_DELAY_USECS \
|
||||
(XCVR_RX_START_DELAY_USECS + XCVR_PROC_DELAY_USECS)
|
||||
|
||||
/*
|
||||
* Define HW whitelist size. This is the total possible whitelist size;
|
||||
* not necessarily the size that will be used (may be smaller)
|
||||
*/
|
||||
#define BLE_HW_WHITE_LIST_SIZE (8)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* H_BLE_XCVR_ */
|
||||
#endif
|
||||
491
lib/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/src/ble_hw.c
Normal file
491
lib/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/src/ble_hw.c
Normal file
@@ -0,0 +1,491 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#if defined(ARDUINO_ARCH_NRF5) && defined(NRF52_SERIES)
|
||||
|
||||
#include <stdint.h>
|
||||
#include <assert.h>
|
||||
#include <string.h>
|
||||
#include "nimble/porting/nimble/include/syscfg/syscfg.h"
|
||||
#include "nimble/porting/nimble/include/os/os.h"
|
||||
#include "../include/ble/xcvr.h"
|
||||
#include "nimble/nimble/include/nimble/ble.h"
|
||||
#include "nimble/nimble/include/nimble/nimble_opt.h"
|
||||
#include "nrf.h"
|
||||
#include "nimble/nimble/controller/include/controller/ble_hw.h"
|
||||
#if MYNEWT
|
||||
#include "mcu/cmsis_nvic.h"
|
||||
#else
|
||||
#include "core_cm4.h"
|
||||
#include "nimble/porting/npl/freertos/include/nimble/nimble_npl_os.h"
|
||||
#endif
|
||||
#include "nimble/porting/nimble/include/os/os_trace_api.h"
|
||||
|
||||
/* Total number of resolving list elements */
|
||||
#define BLE_HW_RESOLV_LIST_SIZE (16)
|
||||
|
||||
/* We use this to keep track of which entries are set to valid addresses */
|
||||
static uint8_t g_ble_hw_whitelist_mask;
|
||||
|
||||
/* Random number generator isr callback */
|
||||
ble_rng_isr_cb_t g_ble_rng_isr_cb;
|
||||
|
||||
/* If LL privacy is enabled, allocate memory for AAR */
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
|
||||
|
||||
/* The NRF51 supports up to 16 IRK entries */
|
||||
#if (MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE) < 16)
|
||||
#define NRF_IRK_LIST_ENTRIES (MYNEWT_VAL(BLE_LL_RESOLV_LIST_SIZE))
|
||||
#else
|
||||
#define NRF_IRK_LIST_ENTRIES (16)
|
||||
#endif
|
||||
|
||||
/* NOTE: each entry is 16 bytes long. */
|
||||
uint32_t g_nrf_irk_list[NRF_IRK_LIST_ENTRIES * 4];
|
||||
|
||||
/* Current number of IRK entries */
|
||||
uint8_t g_nrf_num_irks;
|
||||
|
||||
#endif
|
||||
|
||||
/* Returns public device address or -1 if not present */
|
||||
int
|
||||
ble_hw_get_public_addr(ble_addr_t *addr)
|
||||
{
|
||||
uint32_t addr_high;
|
||||
uint32_t addr_low;
|
||||
|
||||
/* Does FICR have a public address */
|
||||
if ((NRF_FICR->DEVICEADDRTYPE & 1) != 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Copy into device address. We can do this because we know platform */
|
||||
addr_low = NRF_FICR->DEVICEADDR[0];
|
||||
addr_high = NRF_FICR->DEVICEADDR[1];
|
||||
memcpy(addr->val, &addr_low, 4);
|
||||
memcpy(&addr->val[4], &addr_high, 2);
|
||||
addr->type = BLE_ADDR_PUBLIC;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Returns random static address or -1 if not present */
|
||||
int
|
||||
ble_hw_get_static_addr(ble_addr_t *addr)
|
||||
{
|
||||
int rc;
|
||||
|
||||
if ((NRF_FICR->DEVICEADDRTYPE & 1) == 1) {
|
||||
memcpy(addr->val, (void *)&NRF_FICR->DEVICEADDR[0], 4);
|
||||
memcpy(&addr->val[4], (void *)&NRF_FICR->DEVICEADDR[1], 2);
|
||||
addr->val[5] |= 0xc0;
|
||||
addr->type = BLE_ADDR_RANDOM;
|
||||
rc = 0;
|
||||
} else {
|
||||
rc = -1;
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clear the whitelist
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
void
|
||||
ble_hw_whitelist_clear(void)
|
||||
{
|
||||
NRF_RADIO->DACNF = 0;
|
||||
g_ble_hw_whitelist_mask = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a device to the hw whitelist
|
||||
*
|
||||
* @param addr
|
||||
* @param addr_type
|
||||
*
|
||||
* @return int 0: success, BLE error code otherwise
|
||||
*/
|
||||
int
|
||||
ble_hw_whitelist_add(const uint8_t *addr, uint8_t addr_type)
|
||||
{
|
||||
int i;
|
||||
uint32_t mask;
|
||||
|
||||
/* Find first ununsed device address match element */
|
||||
mask = 0x01;
|
||||
for (i = 0; i < BLE_HW_WHITE_LIST_SIZE; ++i) {
|
||||
if ((mask & g_ble_hw_whitelist_mask) == 0) {
|
||||
NRF_RADIO->DAB[i] = get_le32(addr);
|
||||
NRF_RADIO->DAP[i] = get_le16(addr + 4);
|
||||
if (addr_type == BLE_ADDR_RANDOM) {
|
||||
NRF_RADIO->DACNF |= (mask << 8);
|
||||
}
|
||||
g_ble_hw_whitelist_mask |= mask;
|
||||
return BLE_ERR_SUCCESS;
|
||||
}
|
||||
mask <<= 1;
|
||||
}
|
||||
|
||||
return BLE_ERR_MEM_CAPACITY;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a device from the hw whitelist
|
||||
*
|
||||
* @param addr
|
||||
* @param addr_type
|
||||
*
|
||||
*/
|
||||
void
|
||||
ble_hw_whitelist_rmv(const uint8_t *addr, uint8_t addr_type)
|
||||
{
|
||||
int i;
|
||||
uint8_t cfg_addr;
|
||||
uint16_t dap;
|
||||
uint16_t txadd;
|
||||
uint32_t dab;
|
||||
uint32_t mask;
|
||||
|
||||
/* Find first ununsed device address match element */
|
||||
dab = get_le32(addr);
|
||||
dap = get_le16(addr + 4);
|
||||
txadd = NRF_RADIO->DACNF >> 8;
|
||||
mask = 0x01;
|
||||
for (i = 0; i < BLE_HW_WHITE_LIST_SIZE; ++i) {
|
||||
if (mask & g_ble_hw_whitelist_mask) {
|
||||
if ((dab == NRF_RADIO->DAB[i]) && (dap == NRF_RADIO->DAP[i])) {
|
||||
cfg_addr = txadd & mask;
|
||||
if (addr_type == BLE_ADDR_RANDOM) {
|
||||
if (cfg_addr != 0) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (cfg_addr == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
mask <<= 1;
|
||||
}
|
||||
|
||||
if (i < BLE_HW_WHITE_LIST_SIZE) {
|
||||
g_ble_hw_whitelist_mask &= ~mask;
|
||||
NRF_RADIO->DACNF &= ~mask;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of the whitelist in HW
|
||||
*
|
||||
* @return int Number of devices allowed in whitelist
|
||||
*/
|
||||
uint8_t
|
||||
ble_hw_whitelist_size(void)
|
||||
{
|
||||
return BLE_HW_WHITE_LIST_SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enable the whitelisted devices
|
||||
*/
|
||||
void
|
||||
ble_hw_whitelist_enable(void)
|
||||
{
|
||||
/* Enable the configured device addresses */
|
||||
NRF_RADIO->DACNF |= g_ble_hw_whitelist_mask;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disables the whitelisted devices
|
||||
*/
|
||||
void
|
||||
ble_hw_whitelist_disable(void)
|
||||
{
|
||||
/* Disable all whitelist devices */
|
||||
NRF_RADIO->DACNF &= 0x0000ff00;
|
||||
}
|
||||
|
||||
/**
|
||||
* Boolean function which returns true ('1') if there is a match on the
|
||||
* whitelist.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int
|
||||
ble_hw_whitelist_match(void)
|
||||
{
|
||||
return (int)NRF_RADIO->EVENTS_DEVMATCH;
|
||||
}
|
||||
|
||||
/* Encrypt data */
|
||||
int
|
||||
ble_hw_encrypt_block(struct ble_encryption_block *ecb)
|
||||
{
|
||||
int rc;
|
||||
uint32_t end;
|
||||
uint32_t err;
|
||||
|
||||
/* Stop ECB */
|
||||
NRF_ECB->TASKS_STOPECB = 1;
|
||||
/* XXX: does task stop clear these counters? Anyway to do this quicker? */
|
||||
NRF_ECB->EVENTS_ENDECB = 0;
|
||||
NRF_ECB->EVENTS_ERRORECB = 0;
|
||||
NRF_ECB->ECBDATAPTR = (uint32_t)ecb;
|
||||
|
||||
/* Start ECB */
|
||||
NRF_ECB->TASKS_STARTECB = 1;
|
||||
|
||||
/* Wait till error or done */
|
||||
rc = 0;
|
||||
while (1) {
|
||||
end = NRF_ECB->EVENTS_ENDECB;
|
||||
err = NRF_ECB->EVENTS_ERRORECB;
|
||||
if (end || err) {
|
||||
if (err) {
|
||||
rc = -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
/**
|
||||
* Random number generator ISR.
|
||||
*/
|
||||
static void
|
||||
ble_rng_isr(void)
|
||||
{
|
||||
uint8_t rnum;
|
||||
|
||||
os_trace_isr_enter();
|
||||
|
||||
/* No callback? Clear and disable interrupts */
|
||||
if (g_ble_rng_isr_cb == NULL) {
|
||||
NRF_RNG->INTENCLR = 1;
|
||||
NRF_RNG->EVENTS_VALRDY = 0;
|
||||
(void)NRF_RNG->SHORTS;
|
||||
os_trace_isr_exit();
|
||||
return;
|
||||
}
|
||||
|
||||
/* If there is a value ready grab it */
|
||||
if (NRF_RNG->EVENTS_VALRDY) {
|
||||
NRF_RNG->EVENTS_VALRDY = 0;
|
||||
rnum = (uint8_t)NRF_RNG->VALUE;
|
||||
(*g_ble_rng_isr_cb)(rnum);
|
||||
}
|
||||
|
||||
os_trace_isr_exit();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the random number generator
|
||||
*
|
||||
* @param cb
|
||||
* @param bias
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int
|
||||
ble_hw_rng_init(ble_rng_isr_cb_t cb, int bias)
|
||||
{
|
||||
/* Set bias */
|
||||
if (bias) {
|
||||
NRF_RNG->CONFIG = 1;
|
||||
} else {
|
||||
NRF_RNG->CONFIG = 0;
|
||||
}
|
||||
|
||||
/* If we were passed a function pointer we need to enable the interrupt */
|
||||
if (cb != NULL) {
|
||||
#ifndef RIOT_VERSION
|
||||
NVIC_SetPriority(RNG_IRQn, (1 << __NVIC_PRIO_BITS) - 1);
|
||||
#endif
|
||||
#if MYNEWT
|
||||
NVIC_SetVector(RNG_IRQn, (uint32_t)ble_rng_isr);
|
||||
#else
|
||||
ble_npl_hw_set_isr(RNG_IRQn, ble_rng_isr);
|
||||
#endif
|
||||
NVIC_EnableIRQ(RNG_IRQn);
|
||||
g_ble_rng_isr_cb = cb;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Start the random number generator
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int
|
||||
ble_hw_rng_start(void)
|
||||
{
|
||||
os_sr_t sr;
|
||||
|
||||
/* No need for interrupt if there is no callback */
|
||||
OS_ENTER_CRITICAL(sr);
|
||||
NRF_RNG->EVENTS_VALRDY = 0;
|
||||
if (g_ble_rng_isr_cb) {
|
||||
NRF_RNG->INTENSET = 1;
|
||||
}
|
||||
NRF_RNG->TASKS_START = 1;
|
||||
OS_EXIT_CRITICAL(sr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stop the random generator
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
int
|
||||
ble_hw_rng_stop(void)
|
||||
{
|
||||
os_sr_t sr;
|
||||
|
||||
/* No need for interrupt if there is no callback */
|
||||
OS_ENTER_CRITICAL(sr);
|
||||
NRF_RNG->INTENCLR = 1;
|
||||
NRF_RNG->TASKS_STOP = 1;
|
||||
NRF_RNG->EVENTS_VALRDY = 0;
|
||||
OS_EXIT_CRITICAL(sr);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Read the random number generator.
|
||||
*
|
||||
* @return uint8_t
|
||||
*/
|
||||
uint8_t
|
||||
ble_hw_rng_read(void)
|
||||
{
|
||||
uint8_t rnum;
|
||||
|
||||
/* Wait for a sample */
|
||||
while (NRF_RNG->EVENTS_VALRDY == 0) {
|
||||
}
|
||||
|
||||
NRF_RNG->EVENTS_VALRDY = 0;
|
||||
rnum = (uint8_t)NRF_RNG->VALUE;
|
||||
|
||||
return rnum;
|
||||
}
|
||||
|
||||
#if MYNEWT_VAL(BLE_LL_CFG_FEAT_LL_PRIVACY)
|
||||
/**
|
||||
* Clear the resolving list
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
void
|
||||
ble_hw_resolv_list_clear(void)
|
||||
{
|
||||
g_nrf_num_irks = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add a device to the hw resolving list
|
||||
*
|
||||
* @param irk Pointer to IRK to add
|
||||
*
|
||||
* @return int 0: success, BLE error code otherwise
|
||||
*/
|
||||
int
|
||||
ble_hw_resolv_list_add(uint8_t *irk)
|
||||
{
|
||||
uint32_t *nrf_entry;
|
||||
|
||||
/* Find first ununsed device address match element */
|
||||
if (g_nrf_num_irks == NRF_IRK_LIST_ENTRIES) {
|
||||
return BLE_ERR_MEM_CAPACITY;
|
||||
}
|
||||
|
||||
/* Copy into irk list */
|
||||
nrf_entry = &g_nrf_irk_list[4 * g_nrf_num_irks];
|
||||
memcpy(nrf_entry, irk, 16);
|
||||
|
||||
/* Add to total */
|
||||
++g_nrf_num_irks;
|
||||
return BLE_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove a device from the hw resolving list
|
||||
*
|
||||
* @param index Index of IRK to remove
|
||||
*/
|
||||
void
|
||||
ble_hw_resolv_list_rmv(int index)
|
||||
{
|
||||
uint32_t *irk_entry;
|
||||
|
||||
if (index < g_nrf_num_irks) {
|
||||
--g_nrf_num_irks;
|
||||
irk_entry = &g_nrf_irk_list[index];
|
||||
if (g_nrf_num_irks > index) {
|
||||
memmove(irk_entry, irk_entry + 4, 16 * (g_nrf_num_irks - index));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the size of the resolving list. NOTE: this returns the maximum
|
||||
* allowable entries in the HW. Configuration options may limit this.
|
||||
*
|
||||
* @return int Number of devices allowed in resolving list
|
||||
*/
|
||||
uint8_t
|
||||
ble_hw_resolv_list_size(void)
|
||||
{
|
||||
return BLE_HW_RESOLV_LIST_SIZE;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called to determine if the address received was resolved.
|
||||
*
|
||||
* @return int Negative values indicate unresolved address; positive values
|
||||
* indicate index in resolving list of resolved address.
|
||||
*/
|
||||
int
|
||||
ble_hw_resolv_list_match(void)
|
||||
{
|
||||
uint32_t index;
|
||||
|
||||
if (NRF_AAR->EVENTS_END) {
|
||||
if (NRF_AAR->EVENTS_RESOLVED) {
|
||||
index = NRF_AAR->STATUS;
|
||||
return (int)index;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
2120
lib/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/src/ble_phy.c
Normal file
2120
lib/NimBLE-Arduino/src/nimble/nimble/drivers/nrf52/src/ble_phy.c
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#if defined(ARDUINO_ARCH_NRF5) && defined(NRF52_SERIES)
|
||||
|
||||
#include <stdint.h>
|
||||
#include "nimble/porting/nimble/include/syscfg/syscfg.h"
|
||||
#include "nimble/porting/nimble/include/os/os_trace_api.h"
|
||||
|
||||
#if MYNEWT_VAL(BLE_PHY_SYSVIEW)
|
||||
|
||||
static os_trace_module_t g_ble_phy_trace_mod;
|
||||
uint32_t ble_phy_trace_off;
|
||||
|
||||
static void
|
||||
ble_phy_trace_module_send_desc(void)
|
||||
{
|
||||
os_trace_module_desc(&g_ble_phy_trace_mod, "0 phy_set_tx cputime=%u usecs=%u");
|
||||
os_trace_module_desc(&g_ble_phy_trace_mod, "1 phy_set_rx cputime=%u usecs=%u");
|
||||
os_trace_module_desc(&g_ble_phy_trace_mod, "2 phy_disable");
|
||||
}
|
||||
|
||||
void
|
||||
ble_phy_trace_init(void)
|
||||
{
|
||||
ble_phy_trace_off =
|
||||
os_trace_module_register(&g_ble_phy_trace_mod, "ble_phy", 3,
|
||||
ble_phy_trace_module_send_desc);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
194
lib/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_att.h
Normal file
194
lib/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_att.h
Normal file
@@ -0,0 +1,194 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef H_BLE_ATT_
|
||||
#define H_BLE_ATT_
|
||||
|
||||
/**
|
||||
* @brief Bluetooth Attribute Protocol (ATT)
|
||||
* @defgroup bt_att Bluetooth Attribute Protocol (ATT)
|
||||
* @ingroup bt_host
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include "nimble/porting/nimble/include/os/queue.h"
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct os_mbuf;
|
||||
|
||||
#define BLE_ATT_UUID_PRIMARY_SERVICE 0x2800
|
||||
#define BLE_ATT_UUID_SECONDARY_SERVICE 0x2801
|
||||
#define BLE_ATT_UUID_INCLUDE 0x2802
|
||||
#define BLE_ATT_UUID_CHARACTERISTIC 0x2803
|
||||
|
||||
#define BLE_ATT_ERR_INVALID_HANDLE 0x01
|
||||
#define BLE_ATT_ERR_READ_NOT_PERMITTED 0x02
|
||||
#define BLE_ATT_ERR_WRITE_NOT_PERMITTED 0x03
|
||||
#define BLE_ATT_ERR_INVALID_PDU 0x04
|
||||
#define BLE_ATT_ERR_INSUFFICIENT_AUTHEN 0x05
|
||||
#define BLE_ATT_ERR_REQ_NOT_SUPPORTED 0x06
|
||||
#define BLE_ATT_ERR_INVALID_OFFSET 0x07
|
||||
#define BLE_ATT_ERR_INSUFFICIENT_AUTHOR 0x08
|
||||
#define BLE_ATT_ERR_PREPARE_QUEUE_FULL 0x09
|
||||
#define BLE_ATT_ERR_ATTR_NOT_FOUND 0x0a
|
||||
#define BLE_ATT_ERR_ATTR_NOT_LONG 0x0b
|
||||
#define BLE_ATT_ERR_INSUFFICIENT_KEY_SZ 0x0c
|
||||
#define BLE_ATT_ERR_INVALID_ATTR_VALUE_LEN 0x0d
|
||||
#define BLE_ATT_ERR_UNLIKELY 0x0e
|
||||
#define BLE_ATT_ERR_INSUFFICIENT_ENC 0x0f
|
||||
#define BLE_ATT_ERR_UNSUPPORTED_GROUP 0x10
|
||||
#define BLE_ATT_ERR_INSUFFICIENT_RES 0x11
|
||||
|
||||
#define BLE_ATT_OP_ERROR_RSP 0x01
|
||||
#define BLE_ATT_OP_MTU_REQ 0x02
|
||||
#define BLE_ATT_OP_MTU_RSP 0x03
|
||||
#define BLE_ATT_OP_FIND_INFO_REQ 0x04
|
||||
#define BLE_ATT_OP_FIND_INFO_RSP 0x05
|
||||
#define BLE_ATT_OP_FIND_TYPE_VALUE_REQ 0x06
|
||||
#define BLE_ATT_OP_FIND_TYPE_VALUE_RSP 0x07
|
||||
#define BLE_ATT_OP_READ_TYPE_REQ 0x08
|
||||
#define BLE_ATT_OP_READ_TYPE_RSP 0x09
|
||||
#define BLE_ATT_OP_READ_REQ 0x0a
|
||||
#define BLE_ATT_OP_READ_RSP 0x0b
|
||||
#define BLE_ATT_OP_READ_BLOB_REQ 0x0c
|
||||
#define BLE_ATT_OP_READ_BLOB_RSP 0x0d
|
||||
#define BLE_ATT_OP_READ_MULT_REQ 0x0e
|
||||
#define BLE_ATT_OP_READ_MULT_RSP 0x0f
|
||||
#define BLE_ATT_OP_READ_GROUP_TYPE_REQ 0x10
|
||||
#define BLE_ATT_OP_READ_GROUP_TYPE_RSP 0x11
|
||||
#define BLE_ATT_OP_WRITE_REQ 0x12
|
||||
#define BLE_ATT_OP_WRITE_RSP 0x13
|
||||
#define BLE_ATT_OP_PREP_WRITE_REQ 0x16
|
||||
#define BLE_ATT_OP_PREP_WRITE_RSP 0x17
|
||||
#define BLE_ATT_OP_EXEC_WRITE_REQ 0x18
|
||||
#define BLE_ATT_OP_EXEC_WRITE_RSP 0x19
|
||||
#define BLE_ATT_OP_NOTIFY_REQ 0x1b
|
||||
#define BLE_ATT_OP_INDICATE_REQ 0x1d
|
||||
#define BLE_ATT_OP_INDICATE_RSP 0x1e
|
||||
#define BLE_ATT_OP_WRITE_CMD 0x52
|
||||
|
||||
#define BLE_ATT_ATTR_MAX_LEN 512
|
||||
|
||||
#define BLE_ATT_F_READ 0x01
|
||||
#define BLE_ATT_F_WRITE 0x02
|
||||
#define BLE_ATT_F_READ_ENC 0x04
|
||||
#define BLE_ATT_F_READ_AUTHEN 0x08
|
||||
#define BLE_ATT_F_READ_AUTHOR 0x10
|
||||
#define BLE_ATT_F_WRITE_ENC 0x20
|
||||
#define BLE_ATT_F_WRITE_AUTHEN 0x40
|
||||
#define BLE_ATT_F_WRITE_AUTHOR 0x80
|
||||
|
||||
#define HA_FLAG_PERM_RW (BLE_ATT_F_READ | BLE_ATT_F_WRITE)
|
||||
|
||||
#define BLE_ATT_ACCESS_OP_READ 1
|
||||
#define BLE_ATT_ACCESS_OP_WRITE 2
|
||||
|
||||
/** Default ATT MTU. Also the minimum. */
|
||||
#define BLE_ATT_MTU_DFLT 23
|
||||
|
||||
/**
|
||||
* An ATT MTU of 527 allows the largest ATT command (signed write) to contain a
|
||||
* 512-byte attribute value.
|
||||
*/
|
||||
#define BLE_ATT_MTU_MAX 527
|
||||
|
||||
/**
|
||||
* Reads a locally registered attribute. If the specified attribute handle
|
||||
* corresponds to a GATT characteristic value or descriptor, the read is
|
||||
* performed by calling the registered GATT access callback.
|
||||
*
|
||||
* @param attr_handle The 16-bit handle of the attribute to read.
|
||||
* @param out_om On success, this is made to point to a
|
||||
* newly-allocated mbuf containing the
|
||||
* attribute data read.
|
||||
*
|
||||
* @return 0 on success;
|
||||
* NimBLE host ATT return code if the attribute
|
||||
* access callback reports failure;
|
||||
* NimBLE host core return code on unexpected
|
||||
* error.
|
||||
*/
|
||||
int ble_att_svr_read_local(uint16_t attr_handle, struct os_mbuf **out_om);
|
||||
|
||||
/**
|
||||
* Writes a locally registered attribute. This function consumes the supplied
|
||||
* mbuf regardless of the outcome. If the specified attribute handle
|
||||
* corresponds to a GATT characteristic value or descriptor, the write is
|
||||
* performed by calling the registered GATT access callback.
|
||||
*
|
||||
* @param attr_handle The 16-bit handle of the attribute to write.
|
||||
* @param om The value to write to the attribute.
|
||||
*
|
||||
* @return 0 on success;
|
||||
* NimBLE host ATT return code if the attribute
|
||||
* access callback reports failure;
|
||||
* NimBLE host core return code on unexpected
|
||||
* error.
|
||||
*/
|
||||
int ble_att_svr_write_local(uint16_t attr_handle, struct os_mbuf *om);
|
||||
|
||||
/**
|
||||
* Retrieves the ATT MTU of the specified connection. If an MTU exchange for
|
||||
* this connection has occurred, the MTU is the lower of the two peers'
|
||||
* preferred values. Otherwise, the MTU is the default value of 23.
|
||||
*
|
||||
* @param conn_handle The handle of the connection to query.
|
||||
*
|
||||
* @return The specified connection's ATT MTU, or 0 if
|
||||
* there is no such connection.
|
||||
*/
|
||||
uint16_t ble_att_mtu(uint16_t conn_handle);
|
||||
|
||||
/**
|
||||
* Retrieves the preferred ATT MTU. This is the value indicated by the device
|
||||
* during an ATT MTU exchange.
|
||||
*
|
||||
* @return The preferred ATT MTU.
|
||||
*/
|
||||
uint16_t ble_att_preferred_mtu(void);
|
||||
|
||||
/**
|
||||
* Sets the preferred ATT MTU; the device will indicate this value in all
|
||||
* subsequent ATT MTU exchanges. The ATT MTU of a connection is equal to the
|
||||
* lower of the two peers' preferred MTU values. The ATT MTU is what dictates
|
||||
* the maximum size of any message sent during a GATT procedure.
|
||||
*
|
||||
* The specified MTU must be within the following range: [23, BLE_ATT_MTU_MAX].
|
||||
* 23 is a minimum imposed by the Bluetooth specification; BLE_ATT_MTU_MAX is a
|
||||
* NimBLE compile-time setting.
|
||||
*
|
||||
* @param mtu The preferred ATT MTU.
|
||||
*
|
||||
* @return 0 on success;
|
||||
* BLE_HS_EINVAL if the specified value is not
|
||||
* within the allowed range.
|
||||
*/
|
||||
int ble_att_set_preferred_mtu(uint16_t mtu);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef H_BLE_EDDYSTONE_
|
||||
#define H_BLE_EDDYSTONE_
|
||||
|
||||
/**
|
||||
* @brief Eddystone - BLE beacon from Google
|
||||
* @defgroup bt_eddystone Eddystone - BLE beacon from Google
|
||||
* @ingroup bt_host
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct ble_hs_adv_fields;
|
||||
|
||||
#define BLE_EDDYSTONE_MAX_UUIDS16 3
|
||||
#define BLE_EDDYSTONE_URL_MAX_LEN 17
|
||||
|
||||
#define BLE_EDDYSTONE_URL_SCHEME_HTTP_WWW 0
|
||||
#define BLE_EDDYSTONE_URL_SCHEME_HTTPS_WWW 1
|
||||
#define BLE_EDDYSTONE_URL_SCHEME_HTTP 2
|
||||
#define BLE_EDDYSTONE_URL_SCHEME_HTTPS 3
|
||||
|
||||
#define BLE_EDDYSTONE_URL_SUFFIX_COM_SLASH 0x00
|
||||
#define BLE_EDDYSTONE_URL_SUFFIX_ORG_SLASH 0x01
|
||||
#define BLE_EDDYSTONE_URL_SUFFIX_EDU_SLASH 0x02
|
||||
#define BLE_EDDYSTONE_URL_SUFFIX_NET_SLASH 0x03
|
||||
#define BLE_EDDYSTONE_URL_SUFFIX_INFO_SLASH 0x04
|
||||
#define BLE_EDDYSTONE_URL_SUFFIX_BIZ_SLASH 0x05
|
||||
#define BLE_EDDYSTONE_URL_SUFFIX_GOV_SLASH 0x06
|
||||
#define BLE_EDDYSTONE_URL_SUFFIX_COM 0x07
|
||||
#define BLE_EDDYSTONE_URL_SUFFIX_ORG 0x08
|
||||
#define BLE_EDDYSTONE_URL_SUFFIX_EDU 0x09
|
||||
#define BLE_EDDYSTONE_URL_SUFFIX_NET 0x0a
|
||||
#define BLE_EDDYSTONE_URL_SUFFIX_INFO 0x0b
|
||||
#define BLE_EDDYSTONE_URL_SUFFIX_BIZ 0x0c
|
||||
#define BLE_EDDYSTONE_URL_SUFFIX_GOV 0x0d
|
||||
#define BLE_EDDYSTONE_URL_SUFFIX_NONE 0xff
|
||||
|
||||
/**
|
||||
* Configures the device to advertise Eddystone UID beacons.
|
||||
*
|
||||
* @param adv_fields The base advertisement fields to transform into
|
||||
* an eddystone beacon. All configured fields
|
||||
* are preserved; you probably want to clear
|
||||
* this struct before calling this function.
|
||||
* @param uid The 16-byte UID to advertise.
|
||||
* @param measured_power The Measured Power (RSSI value at 0 Meter).
|
||||
*
|
||||
* @return 0 on success;
|
||||
* BLE_HS_EBUSY if advertising is in progress;
|
||||
* BLE_HS_EMSGSIZE if the specified data is too
|
||||
* large to fit in an advertisement;
|
||||
* Other nonzero on failure.
|
||||
*/
|
||||
int ble_eddystone_set_adv_data_uid(struct ble_hs_adv_fields *adv_fields,
|
||||
void *uid, int8_t measured_power);
|
||||
|
||||
/**
|
||||
* Configures the device to advertise Eddystone URL beacons.
|
||||
*
|
||||
* @param adv_fields The base advertisement fields to transform into
|
||||
* an eddystone beacon. All configured fields
|
||||
* are preserved; you probably want to clear
|
||||
* this struct before calling this function.
|
||||
* @param url_scheme The prefix of the URL; one of the
|
||||
* BLE_EDDYSTONE_URL_SCHEME values.
|
||||
* @param url_body The middle of the URL. Don't include the
|
||||
* suffix if there is a suitable suffix code.
|
||||
* @param url_body_len The string length of the url_body argument.
|
||||
* @param url_suffix The suffix of the URL; one of the
|
||||
* BLE_EDDYSTONE_URL_SUFFIX values; use
|
||||
* BLE_EDDYSTONE_URL_SUFFIX_NONE if the suffix
|
||||
* is embedded in the body argument.
|
||||
* @param measured_power The Measured Power (RSSI value at 0 Meter).
|
||||
*
|
||||
* @return 0 on success;
|
||||
* BLE_HS_EBUSY if advertising is in progress;
|
||||
* BLE_HS_EMSGSIZE if the specified data is too
|
||||
* large to fit in an advertisement;
|
||||
* Other nonzero on failure.
|
||||
*/
|
||||
int ble_eddystone_set_adv_data_url(struct ble_hs_adv_fields *adv_fields,
|
||||
uint8_t url_scheme, char *url_body,
|
||||
uint8_t url_body_len, uint8_t suffix,
|
||||
int8_t measured_power);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif
|
||||
2094
lib/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_gap.h
Normal file
2094
lib/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_gap.h
Normal file
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,902 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef H_BLE_GATT_
|
||||
#define H_BLE_GATT_
|
||||
|
||||
/**
|
||||
* @brief Bluetooth Generic Attribute Profile (GATT)
|
||||
* @defgroup bt_gatt Bluetooth Generic Attribute Profile (GATT)
|
||||
* @ingroup bt_host
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "ble_att.h"
|
||||
#include "ble_uuid.h"
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct ble_hs_conn;
|
||||
struct ble_att_error_rsp;
|
||||
struct ble_hs_cfg;
|
||||
|
||||
#define BLE_GATT_REGISTER_OP_SVC 1
|
||||
#define BLE_GATT_REGISTER_OP_CHR 2
|
||||
#define BLE_GATT_REGISTER_OP_DSC 3
|
||||
|
||||
#define BLE_GATT_SVC_UUID16 0x1801
|
||||
#define BLE_GATT_DSC_CLT_CFG_UUID16 0x2902
|
||||
|
||||
#define BLE_GATT_CHR_PROP_BROADCAST 0x01
|
||||
#define BLE_GATT_CHR_PROP_READ 0x02
|
||||
#define BLE_GATT_CHR_PROP_WRITE_NO_RSP 0x04
|
||||
#define BLE_GATT_CHR_PROP_WRITE 0x08
|
||||
#define BLE_GATT_CHR_PROP_NOTIFY 0x10
|
||||
#define BLE_GATT_CHR_PROP_INDICATE 0x20
|
||||
#define BLE_GATT_CHR_PROP_AUTH_SIGN_WRITE 0x40
|
||||
#define BLE_GATT_CHR_PROP_EXTENDED 0x80
|
||||
|
||||
#define BLE_GATT_ACCESS_OP_READ_CHR 0
|
||||
#define BLE_GATT_ACCESS_OP_WRITE_CHR 1
|
||||
#define BLE_GATT_ACCESS_OP_READ_DSC 2
|
||||
#define BLE_GATT_ACCESS_OP_WRITE_DSC 3
|
||||
|
||||
#define BLE_GATT_CHR_F_BROADCAST 0x0001
|
||||
#define BLE_GATT_CHR_F_READ 0x0002
|
||||
#define BLE_GATT_CHR_F_WRITE_NO_RSP 0x0004
|
||||
#define BLE_GATT_CHR_F_WRITE 0x0008
|
||||
#define BLE_GATT_CHR_F_NOTIFY 0x0010
|
||||
#define BLE_GATT_CHR_F_INDICATE 0x0020
|
||||
#define BLE_GATT_CHR_F_AUTH_SIGN_WRITE 0x0040
|
||||
#define BLE_GATT_CHR_F_RELIABLE_WRITE 0x0080
|
||||
#define BLE_GATT_CHR_F_AUX_WRITE 0x0100
|
||||
#define BLE_GATT_CHR_F_READ_ENC 0x0200
|
||||
#define BLE_GATT_CHR_F_READ_AUTHEN 0x0400
|
||||
#define BLE_GATT_CHR_F_READ_AUTHOR 0x0800
|
||||
#define BLE_GATT_CHR_F_WRITE_ENC 0x1000
|
||||
#define BLE_GATT_CHR_F_WRITE_AUTHEN 0x2000
|
||||
#define BLE_GATT_CHR_F_WRITE_AUTHOR 0x4000
|
||||
|
||||
#define BLE_GATT_SVC_TYPE_END 0
|
||||
#define BLE_GATT_SVC_TYPE_PRIMARY 1
|
||||
#define BLE_GATT_SVC_TYPE_SECONDARY 2
|
||||
|
||||
/*** @client. */
|
||||
struct ble_gatt_error {
|
||||
uint16_t status;
|
||||
uint16_t att_handle;
|
||||
};
|
||||
|
||||
struct ble_gatt_svc {
|
||||
uint16_t start_handle;
|
||||
uint16_t end_handle;
|
||||
ble_uuid_any_t uuid;
|
||||
};
|
||||
|
||||
struct ble_gatt_attr {
|
||||
uint16_t handle;
|
||||
uint16_t offset;
|
||||
struct os_mbuf *om;
|
||||
};
|
||||
|
||||
struct ble_gatt_chr {
|
||||
uint16_t def_handle;
|
||||
uint16_t val_handle;
|
||||
uint8_t properties;
|
||||
ble_uuid_any_t uuid;
|
||||
};
|
||||
|
||||
struct ble_gatt_dsc {
|
||||
uint16_t handle;
|
||||
ble_uuid_any_t uuid;
|
||||
};
|
||||
|
||||
typedef int ble_gatt_mtu_fn(uint16_t conn_handle,
|
||||
const struct ble_gatt_error *error,
|
||||
uint16_t mtu, void *arg);
|
||||
typedef int ble_gatt_disc_svc_fn(uint16_t conn_handle,
|
||||
const struct ble_gatt_error *error,
|
||||
const struct ble_gatt_svc *service,
|
||||
void *arg);
|
||||
|
||||
/**
|
||||
* The host will free the attribute mbuf automatically after the callback is
|
||||
* executed. The application can take ownership of the mbuf and prevent it
|
||||
* from being freed by assigning NULL to attr->om.
|
||||
*/
|
||||
typedef int ble_gatt_attr_fn(uint16_t conn_handle,
|
||||
const struct ble_gatt_error *error,
|
||||
struct ble_gatt_attr *attr,
|
||||
void *arg);
|
||||
|
||||
/**
|
||||
* The host will free the attribute mbufs automatically after the callback is
|
||||
* executed. The application can take ownership of the mbufs and prevent them
|
||||
* from being freed by assigning NULL to each attribute's om field.
|
||||
*/
|
||||
typedef int ble_gatt_reliable_attr_fn(uint16_t conn_handle,
|
||||
const struct ble_gatt_error *error,
|
||||
struct ble_gatt_attr *attrs,
|
||||
uint8_t num_attrs, void *arg);
|
||||
|
||||
typedef int ble_gatt_chr_fn(uint16_t conn_handle,
|
||||
const struct ble_gatt_error *error,
|
||||
const struct ble_gatt_chr *chr, void *arg);
|
||||
|
||||
typedef int ble_gatt_dsc_fn(uint16_t conn_handle,
|
||||
const struct ble_gatt_error *error,
|
||||
uint16_t chr_val_handle,
|
||||
const struct ble_gatt_dsc *dsc,
|
||||
void *arg);
|
||||
|
||||
/**
|
||||
* Initiates GATT procedure: Exchange MTU.
|
||||
*
|
||||
* @param conn_handle The connection over which to execute the
|
||||
* procedure.
|
||||
* @param cb The function to call to report procedure status
|
||||
* updates; null for no callback.
|
||||
* @param cb_arg The optional argument to pass to the callback
|
||||
* function.
|
||||
*
|
||||
* @return 0 on success; nonzero on failure.
|
||||
*/
|
||||
int ble_gattc_exchange_mtu(uint16_t conn_handle,
|
||||
ble_gatt_mtu_fn *cb, void *cb_arg);
|
||||
|
||||
/**
|
||||
* Initiates GATT procedure: Discover All Primary Services.
|
||||
*
|
||||
* @param conn_handle The connection over which to execute the
|
||||
* procedure.
|
||||
* @param cb The function to call to report procedure status
|
||||
* updates; null for no callback.
|
||||
* @param cb_arg The optional argument to pass to the callback
|
||||
* function.
|
||||
*/
|
||||
int ble_gattc_disc_all_svcs(uint16_t conn_handle,
|
||||
ble_gatt_disc_svc_fn *cb, void *cb_arg);
|
||||
|
||||
/**
|
||||
* Initiates GATT procedure: Discover Primary Service by Service UUID.
|
||||
*
|
||||
* @param conn_handle The connection over which to execute the
|
||||
* procedure.
|
||||
* @param service_uuid128 The 128-bit UUID of the service to discover.
|
||||
* @param cb The function to call to report procedure status
|
||||
* updates; null for no callback.
|
||||
* @param cb_arg The optional argument to pass to the callback
|
||||
* function.
|
||||
*
|
||||
* @return 0 on success; nonzero on failure.
|
||||
*/
|
||||
int ble_gattc_disc_svc_by_uuid(uint16_t conn_handle, const ble_uuid_t *uuid,
|
||||
ble_gatt_disc_svc_fn *cb, void *cb_arg);
|
||||
|
||||
/**
|
||||
* Initiates GATT procedure: Find Included Services.
|
||||
*
|
||||
* @param conn_handle The connection over which to execute the
|
||||
* procedure.
|
||||
* @param start_handle The handle to begin the search at (generally
|
||||
* the service definition handle).
|
||||
* @param end_handle The handle to end the search at (generally the
|
||||
* last handle in the service).
|
||||
* @param cb The function to call to report procedure status
|
||||
* updates; null for no callback.
|
||||
* @param cb_arg The optional argument to pass to the callback
|
||||
* function.
|
||||
*
|
||||
* @return 0 on success; nonzero on failure.
|
||||
*/
|
||||
int ble_gattc_find_inc_svcs(uint16_t conn_handle, uint16_t start_handle,
|
||||
uint16_t end_handle,
|
||||
ble_gatt_disc_svc_fn *cb, void *cb_arg);
|
||||
|
||||
/**
|
||||
* Initiates GATT procedure: Discover All Characteristics of a Service.
|
||||
*
|
||||
* @param conn_handle The connection over which to execute the
|
||||
* procedure.
|
||||
* @param start_handle The handle to begin the search at (generally
|
||||
* the service definition handle).
|
||||
* @param end_handle The handle to end the search at (generally the
|
||||
* last handle in the service).
|
||||
* @param cb The function to call to report procedure status
|
||||
* updates; null for no callback.
|
||||
* @param cb_arg The optional argument to pass to the callback
|
||||
* function.
|
||||
*
|
||||
* @return 0 on success; nonzero on failure.
|
||||
*/
|
||||
int ble_gattc_disc_all_chrs(uint16_t conn_handle, uint16_t start_handle,
|
||||
uint16_t end_handle, ble_gatt_chr_fn *cb,
|
||||
void *cb_arg);
|
||||
|
||||
/**
|
||||
* Initiates GATT procedure: Discover Characteristics by UUID.
|
||||
*
|
||||
* @param conn_handle The connection over which to execute the
|
||||
* procedure.
|
||||
* @param start_handle The handle to begin the search at (generally
|
||||
* the service definition handle).
|
||||
* @param end_handle The handle to end the search at (generally the
|
||||
* last handle in the service).
|
||||
* @param chr_uuid128 The 128-bit UUID of the characteristic to
|
||||
* discover.
|
||||
* @param cb The function to call to report procedure status
|
||||
* updates; null for no callback.
|
||||
* @param cb_arg The optional argument to pass to the callback
|
||||
* function.
|
||||
*
|
||||
* @return 0 on success; nonzero on failure.
|
||||
*/
|
||||
int ble_gattc_disc_chrs_by_uuid(uint16_t conn_handle, uint16_t start_handle,
|
||||
uint16_t end_handle, const ble_uuid_t *uuid,
|
||||
ble_gatt_chr_fn *cb, void *cb_arg);
|
||||
|
||||
/**
|
||||
* Initiates GATT procedure: Discover All Characteristic Descriptors.
|
||||
*
|
||||
* @param conn_handle The connection over which to execute the
|
||||
* procedure.
|
||||
* @param chr_val_handle The handle of the characteristic value
|
||||
* attribute.
|
||||
* @param chr_end_handle The last handle in the characteristic
|
||||
* definition.
|
||||
* @param cb The function to call to report procedure status
|
||||
* updates; null for no callback.
|
||||
* @param cb_arg The optional argument to pass to the callback
|
||||
* function.
|
||||
*
|
||||
* @return 0 on success; nonzero on failure.
|
||||
*/
|
||||
int ble_gattc_disc_all_dscs(uint16_t conn_handle, uint16_t start_handle,
|
||||
uint16_t end_handle,
|
||||
ble_gatt_dsc_fn *cb, void *cb_arg);
|
||||
|
||||
/**
|
||||
* Initiates GATT procedure: Read Characteristic Value.
|
||||
*
|
||||
* @param conn_handle The connection over which to execute the
|
||||
* procedure.
|
||||
* @param attr_handle The handle of the characteristic value to read.
|
||||
* @param cb The function to call to report procedure status
|
||||
* updates; null for no callback.
|
||||
* @param cb_arg The optional argument to pass to the callback
|
||||
* function.
|
||||
*
|
||||
* @return 0 on success; nonzero on failure.
|
||||
*/
|
||||
int ble_gattc_read(uint16_t conn_handle, uint16_t attr_handle,
|
||||
ble_gatt_attr_fn *cb, void *cb_arg);
|
||||
|
||||
/**
|
||||
* Initiates GATT procedure: Read Using Characteristic UUID.
|
||||
*
|
||||
* @param conn_handle The connection over which to execute the
|
||||
* procedure.
|
||||
* @param start_handle The first handle to search (generally the
|
||||
* handle of the service definition).
|
||||
* @param end_handle The last handle to search (generally the
|
||||
* last handle in the service definition).
|
||||
* @param cb The function to call to report procedure status
|
||||
* updates; null for no callback.
|
||||
* @param cb_arg The optional argument to pass to the callback
|
||||
* function.
|
||||
*
|
||||
* @return 0 on success; nonzero on failure.
|
||||
*/
|
||||
int ble_gattc_read_by_uuid(uint16_t conn_handle, uint16_t start_handle,
|
||||
uint16_t end_handle, const ble_uuid_t *uuid,
|
||||
ble_gatt_attr_fn *cb, void *cb_arg);
|
||||
|
||||
/**
|
||||
* Initiates GATT procedure: Read Long Characteristic Values.
|
||||
*
|
||||
* @param conn_handle The connection over which to execute the
|
||||
* procedure.
|
||||
* @param handle The handle of the characteristic value to read.
|
||||
* @param cb The function to call to report procedure status
|
||||
* updates; null for no callback.
|
||||
* @param cb_arg The optional argument to pass to the callback
|
||||
* function.
|
||||
*
|
||||
* @return 0 on success; nonzero on failure.
|
||||
*/
|
||||
int ble_gattc_read_long(uint16_t conn_handle, uint16_t handle, uint16_t offset,
|
||||
ble_gatt_attr_fn *cb, void *cb_arg);
|
||||
|
||||
/**
|
||||
* Initiates GATT procedure: Read Multiple Characteristic Values.
|
||||
*
|
||||
* @param conn_handle The connection over which to execute the
|
||||
* procedure.
|
||||
* @param handles An array of 16-bit attribute handles to read.
|
||||
* @param num_handles The number of entries in the "handles" array.
|
||||
* @param cb The function to call to report procedure status
|
||||
* updates; null for no callback.
|
||||
* @param cb_arg The optional argument to pass to the callback
|
||||
* function.
|
||||
*
|
||||
* @return 0 on success; nonzero on failure.
|
||||
*/
|
||||
int ble_gattc_read_mult(uint16_t conn_handle, const uint16_t *handles,
|
||||
uint8_t num_handles, ble_gatt_attr_fn *cb,
|
||||
void *cb_arg);
|
||||
|
||||
/**
|
||||
* Initiates GATT procedure: Write Without Response. This function consumes
|
||||
* the supplied mbuf regardless of the outcome.
|
||||
*
|
||||
* @param conn_handle The connection over which to execute the
|
||||
* procedure.
|
||||
* @param attr_handle The handle of the characteristic value to write
|
||||
* to.
|
||||
* @param txom The value to write to the characteristic.
|
||||
*
|
||||
* @return 0 on success; nonzero on failure.
|
||||
*/
|
||||
int ble_gattc_write_no_rsp(uint16_t conn_handle, uint16_t attr_handle,
|
||||
struct os_mbuf *om);
|
||||
|
||||
/**
|
||||
* Initiates GATT procedure: Write Without Response. This function consumes
|
||||
* the supplied mbuf regardless of the outcome.
|
||||
*
|
||||
* @param conn_handle The connection over which to execute the
|
||||
* procedure.
|
||||
* @param attr_handle The handle of the characteristic value to write
|
||||
* to.
|
||||
* @param value The value to write to the characteristic.
|
||||
* @param value_len The number of bytes to write.
|
||||
*
|
||||
* @return 0 on success; nonzero on failure.
|
||||
*/
|
||||
int ble_gattc_write_no_rsp_flat(uint16_t conn_handle, uint16_t attr_handle,
|
||||
const void *data, uint16_t data_len);
|
||||
|
||||
/**
|
||||
* Initiates GATT procedure: Write Characteristic Value. This function
|
||||
* consumes the supplied mbuf regardless of the outcome.
|
||||
*
|
||||
* @param conn_handle The connection over which to execute the
|
||||
* procedure.
|
||||
* @param attr_handle The handle of the characteristic value to write
|
||||
* to.
|
||||
* @param txom The value to write to the characteristic.
|
||||
* @param cb The function to call to report procedure status
|
||||
* updates; null for no callback.
|
||||
* @param cb_arg The optional argument to pass to the callback
|
||||
* function.
|
||||
*
|
||||
* @return 0 on success; nonzero on failure.
|
||||
*/
|
||||
int ble_gattc_write(uint16_t conn_handle, uint16_t attr_handle,
|
||||
struct os_mbuf *om,
|
||||
ble_gatt_attr_fn *cb, void *cb_arg);
|
||||
|
||||
/**
|
||||
* Initiates GATT procedure: Write Characteristic Value (flat buffer version).
|
||||
*
|
||||
* @param conn_handle The connection over which to execute the
|
||||
* procedure.
|
||||
* @param attr_handle The handle of the characteristic value to write
|
||||
* to.
|
||||
* @param value The value to write to the characteristic.
|
||||
* @param value_len The number of bytes to write.
|
||||
* @param cb The function to call to report procedure status
|
||||
* updates; null for no callback.
|
||||
* @param cb_arg The optional argument to pass to the callback
|
||||
* function.
|
||||
*
|
||||
* @return 0 on success; nonzero on failure.
|
||||
*/
|
||||
int ble_gattc_write_flat(uint16_t conn_handle, uint16_t attr_handle,
|
||||
const void *data, uint16_t data_len,
|
||||
ble_gatt_attr_fn *cb, void *cb_arg);
|
||||
|
||||
/**
|
||||
* Initiates GATT procedure: Write Long Characteristic Values. This function
|
||||
* consumes the supplied mbuf regardless of the outcome.
|
||||
*
|
||||
* @param conn_handle The connection over which to execute the
|
||||
* procedure.
|
||||
* @param attr_handle The handle of the characteristic value to write
|
||||
* to.
|
||||
* @param txom The value to write to the characteristic.
|
||||
* @param cb The function to call to report procedure status
|
||||
* updates; null for no callback.
|
||||
* @param cb_arg The optional argument to pass to the callback
|
||||
* function.
|
||||
*
|
||||
* @return 0 on success; nonzero on failure.
|
||||
*/
|
||||
int ble_gattc_write_long(uint16_t conn_handle, uint16_t attr_handle,
|
||||
uint16_t offset, struct os_mbuf *om,
|
||||
ble_gatt_attr_fn *cb, void *cb_arg);
|
||||
|
||||
/**
|
||||
* Initiates GATT procedure: Reliable Writes. This function consumes the
|
||||
* supplied mbufs regardless of the outcome.
|
||||
*
|
||||
* @param conn_handle The connection over which to execute the
|
||||
* procedure.
|
||||
* @param attrs An array of attribute descriptors; specifies
|
||||
* which characteristics to write to and what
|
||||
* data to write to them. The mbuf pointer in
|
||||
* each attribute is set to NULL by this
|
||||
* function.
|
||||
* @param num_attrs The number of characteristics to write; equal
|
||||
* to the number of elements in the 'attrs'
|
||||
* array.
|
||||
* @param cb The function to call to report procedure status
|
||||
* updates; null for no callback.
|
||||
* @param cb_arg The optional argument to pass to the callback
|
||||
* function.
|
||||
*/
|
||||
int ble_gattc_write_reliable(uint16_t conn_handle,
|
||||
struct ble_gatt_attr *attrs,
|
||||
int num_attrs, ble_gatt_reliable_attr_fn *cb,
|
||||
void *cb_arg);
|
||||
|
||||
/**
|
||||
* Sends a "free-form" characteristic notification. This function consumes the
|
||||
* supplied mbuf regardless of the outcome.
|
||||
*
|
||||
* @param conn_handle The connection over which to execute the
|
||||
* procedure.
|
||||
* @param chr_val_handle The attribute handle to indicate in the
|
||||
* outgoing notification.
|
||||
* @param txom The value to write to the characteristic.
|
||||
*
|
||||
* @return 0 on success; nonzero on failure.
|
||||
*/
|
||||
int ble_gattc_notify_custom(uint16_t conn_handle, uint16_t att_handle,
|
||||
struct os_mbuf *om);
|
||||
|
||||
/**
|
||||
* Sends a characteristic notification. The content of the message is read
|
||||
* from the specified characteristic.
|
||||
*
|
||||
* @param conn_handle The connection over which to execute the
|
||||
* procedure.
|
||||
* @param chr_val_handle The value attribute handle of the
|
||||
* characteristic to include in the outgoing
|
||||
* notification.
|
||||
*
|
||||
* @return 0 on success; nonzero on failure.
|
||||
*/
|
||||
int ble_gattc_notify(uint16_t conn_handle, uint16_t chr_val_handle);
|
||||
|
||||
/**
|
||||
* Sends a "free-form" characteristic indication. The provided mbuf contains
|
||||
* the indication payload. This function consumes the supplied mbuf regardless
|
||||
* of the outcome.
|
||||
*
|
||||
* @param conn_handle The connection over which to execute the
|
||||
* procedure.
|
||||
* @param chr_val_handle The value attribute handle of the
|
||||
* characteristic to include in the outgoing
|
||||
* indication.
|
||||
* @param txom The data to include in the indication.
|
||||
*
|
||||
* @return 0 on success; nonzero on failure.
|
||||
*/
|
||||
int ble_gattc_indicate_custom(uint16_t conn_handle, uint16_t chr_val_handle,
|
||||
struct os_mbuf *txom);
|
||||
|
||||
/**
|
||||
* Sends a characteristic indication. The content of the message is read from
|
||||
* the specified characteristic.
|
||||
*
|
||||
* @param conn_handle The connection over which to execute the
|
||||
* procedure.
|
||||
* @param chr_val_handle The value attribute handle of the
|
||||
* characteristic to include in the outgoing
|
||||
* indication.
|
||||
*
|
||||
* @return 0 on success; nonzero on failure.
|
||||
*/
|
||||
int ble_gattc_indicate(uint16_t conn_handle, uint16_t chr_val_handle);
|
||||
|
||||
int ble_gattc_init(void);
|
||||
|
||||
/*** @server. */
|
||||
|
||||
struct ble_gatt_access_ctxt;
|
||||
typedef int ble_gatt_access_fn(uint16_t conn_handle, uint16_t attr_handle,
|
||||
struct ble_gatt_access_ctxt *ctxt, void *arg);
|
||||
|
||||
typedef uint16_t ble_gatt_chr_flags;
|
||||
|
||||
struct ble_gatt_chr_def {
|
||||
/**
|
||||
* Pointer to characteristic UUID; use BLE_UUIDxx_DECLARE macros to declare
|
||||
* proper UUID; NULL if there are no more characteristics in the service.
|
||||
*/
|
||||
const ble_uuid_t *uuid;
|
||||
|
||||
/**
|
||||
* Callback that gets executed when this characteristic is read or
|
||||
* written.
|
||||
*/
|
||||
ble_gatt_access_fn *access_cb;
|
||||
|
||||
/** Optional argument for callback. */
|
||||
void *arg;
|
||||
|
||||
/**
|
||||
* Array of this characteristic's descriptors. NULL if no descriptors.
|
||||
* Do not include CCCD; it gets added automatically if this
|
||||
* characteristic's notify or indicate flag is set.
|
||||
*/
|
||||
struct ble_gatt_dsc_def *descriptors;
|
||||
|
||||
/** Specifies the set of permitted operations for this characteristic. */
|
||||
ble_gatt_chr_flags flags;
|
||||
|
||||
/** Specifies minimum required key size to access this characteristic. */
|
||||
uint8_t min_key_size;
|
||||
|
||||
/**
|
||||
* At registration time, this is filled in with the characteristic's value
|
||||
* attribute handle.
|
||||
*/
|
||||
uint16_t *val_handle;
|
||||
};
|
||||
|
||||
struct ble_gatt_svc_def {
|
||||
/**
|
||||
* One of the following:
|
||||
* o BLE_GATT_SVC_TYPE_PRIMARY - primary service
|
||||
* o BLE_GATT_SVC_TYPE_SECONDARY - secondary service
|
||||
* o 0 - No more services in this array.
|
||||
*/
|
||||
uint8_t type;
|
||||
|
||||
/**
|
||||
* Pointer to service UUID; use BLE_UUIDxx_DECLARE macros to declare
|
||||
* proper UUID; NULL if there are no more characteristics in the service.
|
||||
*/
|
||||
const ble_uuid_t *uuid;
|
||||
|
||||
/**
|
||||
* Array of pointers to other service definitions. These services are
|
||||
* reported as "included services" during service discovery. Terminate the
|
||||
* array with NULL.
|
||||
*/
|
||||
const struct ble_gatt_svc_def **includes;
|
||||
|
||||
/**
|
||||
* Array of characteristic definitions corresponding to characteristics
|
||||
* belonging to this service.
|
||||
*/
|
||||
const struct ble_gatt_chr_def *characteristics;
|
||||
};
|
||||
|
||||
struct ble_gatt_dsc_def {
|
||||
/**
|
||||
* Pointer to descriptor UUID; use BLE_UUIDxx_DECLARE macros to declare
|
||||
* proper UUID; NULL if there are no more characteristics in the service.
|
||||
*/
|
||||
const ble_uuid_t *uuid;
|
||||
|
||||
/** Specifies the set of permitted operations for this descriptor. */
|
||||
uint8_t att_flags;
|
||||
|
||||
/** Specifies minimum required key size to access this descriptor. */
|
||||
uint8_t min_key_size;
|
||||
|
||||
/** Callback that gets executed when the descriptor is read or written. */
|
||||
ble_gatt_access_fn *access_cb;
|
||||
|
||||
/** Optional argument for callback. */
|
||||
void *arg;
|
||||
};
|
||||
|
||||
/**
|
||||
* Context for an access to a GATT characteristic or descriptor. When a client
|
||||
* reads or writes a locally registered characteristic or descriptor, an
|
||||
* instance of this struct gets passed to the application callback.
|
||||
*/
|
||||
struct ble_gatt_access_ctxt {
|
||||
/**
|
||||
* Indicates the gatt operation being performed. This is equal to one of
|
||||
* the following values:
|
||||
* o BLE_GATT_ACCESS_OP_READ_CHR
|
||||
* o BLE_GATT_ACCESS_OP_WRITE_CHR
|
||||
* o BLE_GATT_ACCESS_OP_READ_DSC
|
||||
* o BLE_GATT_ACCESS_OP_WRITE_DSC
|
||||
*/
|
||||
uint8_t op;
|
||||
|
||||
/**
|
||||
* A container for the GATT access data.
|
||||
* o For reads: The application populates this with the value of the
|
||||
* characteristic or descriptor being read.
|
||||
* o For writes: This is already populated with the value being written
|
||||
* by the peer. If the application wishes to retain this mbuf for
|
||||
* later use, the access callback must set this pointer to NULL to
|
||||
* prevent the stack from freeing it.
|
||||
*/
|
||||
struct os_mbuf *om;
|
||||
|
||||
/**
|
||||
* The GATT operation being performed dictates which field in this union is
|
||||
* valid. If a characteristic is being accessed, the chr field is valid.
|
||||
* Otherwise a descriptor is being accessed, in which case the dsc field
|
||||
* is valid.
|
||||
*/
|
||||
union {
|
||||
/**
|
||||
* The characteristic definition corresponding to the characteristic
|
||||
* being accessed. This is what the app registered at startup.
|
||||
*/
|
||||
const struct ble_gatt_chr_def *chr;
|
||||
|
||||
/**
|
||||
* The descriptor definition corresponding to the descriptor being
|
||||
* accessed. This is what the app registered at startup.
|
||||
*/
|
||||
const struct ble_gatt_dsc_def *dsc;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* Context passed to the registration callback; represents the GATT service,
|
||||
* characteristic, or descriptor being registered.
|
||||
*/
|
||||
struct ble_gatt_register_ctxt {
|
||||
/**
|
||||
* Indicates the gatt registration operation just performed. This is
|
||||
* equal to one of the following values:
|
||||
* o BLE_GATT_REGISTER_OP_SVC
|
||||
* o BLE_GATT_REGISTER_OP_CHR
|
||||
* o BLE_GATT_REGISTER_OP_DSC
|
||||
*/
|
||||
uint8_t op;
|
||||
|
||||
/**
|
||||
* The value of the op field determines which field in this union is valid.
|
||||
*/
|
||||
union {
|
||||
/** Service; valid if op == BLE_GATT_REGISTER_OP_SVC. */
|
||||
struct {
|
||||
/** The ATT handle of the service definition attribute. */
|
||||
uint16_t handle;
|
||||
|
||||
/**
|
||||
* The service definition representing the service being
|
||||
* registered.
|
||||
*/
|
||||
const struct ble_gatt_svc_def *svc_def;
|
||||
} svc;
|
||||
|
||||
/** Characteristic; valid if op == BLE_GATT_REGISTER_OP_CHR. */
|
||||
struct {
|
||||
/** The ATT handle of the characteristic definition attribute. */
|
||||
uint16_t def_handle;
|
||||
|
||||
/** The ATT handle of the characteristic value attribute. */
|
||||
uint16_t val_handle;
|
||||
|
||||
/**
|
||||
* The characteristic definition representing the characteristic
|
||||
* being registered.
|
||||
*/
|
||||
const struct ble_gatt_chr_def *chr_def;
|
||||
|
||||
/**
|
||||
* The service definition corresponding to the characteristic's
|
||||
* parent service.
|
||||
*/
|
||||
const struct ble_gatt_svc_def *svc_def;
|
||||
} chr;
|
||||
|
||||
/** Descriptor; valid if op == BLE_GATT_REGISTER_OP_DSC. */
|
||||
struct {
|
||||
/** The ATT handle of the descriptor definition attribute. */
|
||||
uint16_t handle;
|
||||
|
||||
/**
|
||||
* The descriptor definition corresponding to the descriptor being
|
||||
* registered.
|
||||
*/
|
||||
const struct ble_gatt_dsc_def *dsc_def;
|
||||
|
||||
/**
|
||||
* The characteristic definition corresponding to the descriptor's
|
||||
* parent characteristic.
|
||||
*/
|
||||
const struct ble_gatt_chr_def *chr_def;
|
||||
|
||||
/**
|
||||
* The service definition corresponding to the descriptor's
|
||||
* grandparent service
|
||||
*/
|
||||
const struct ble_gatt_svc_def *svc_def;
|
||||
} dsc;
|
||||
};
|
||||
};
|
||||
|
||||
typedef void ble_gatt_register_fn(struct ble_gatt_register_ctxt *ctxt,
|
||||
void *arg);
|
||||
|
||||
/**
|
||||
* Queues a set of service definitions for registration. All services queued
|
||||
* in this manner get registered when ble_gatts_start() is called.
|
||||
*
|
||||
* @param svcs An array of service definitions to queue for
|
||||
* registration. This array must be
|
||||
* terminated with an entry whose 'type'
|
||||
* equals 0.
|
||||
*
|
||||
* @return 0 on success;
|
||||
* BLE_HS_ENOMEM on heap exhaustion.
|
||||
*/
|
||||
int ble_gatts_add_svcs(const struct ble_gatt_svc_def *svcs);
|
||||
|
||||
/**
|
||||
* Set visibility of local GATT service. Invisible services are not removed
|
||||
* from database but are not discoverable by peer devices. Service Changed
|
||||
* should be handled by application when needed by calling
|
||||
* ble_svc_gatt_changed().
|
||||
*
|
||||
* @param handle Handle of service
|
||||
* @param visible non-zero if service should be visible
|
||||
*
|
||||
* @return 0 on success;
|
||||
* BLE_HS_ENOENT if service wasn't found.
|
||||
*/
|
||||
int ble_gatts_svc_set_visibility(uint16_t handle, int visible);
|
||||
|
||||
/**
|
||||
* Adjusts a host configuration object's settings to accommodate the specified
|
||||
* service definition array. This function adds the counts to the appropriate
|
||||
* fields in the supplied configuration object without clearing them first, so
|
||||
* it can be called repeatedly with different inputs to calculate totals. Be
|
||||
* sure to zero the GATT server settings prior to the first call to this
|
||||
* function.
|
||||
*
|
||||
* @param defs The service array containing the resource
|
||||
* definitions to be counted.
|
||||
*
|
||||
* @return 0 on success;
|
||||
* BLE_HS_EINVAL if the svcs array contains an
|
||||
* invalid resource definition.
|
||||
*/
|
||||
int ble_gatts_count_cfg(const struct ble_gatt_svc_def *defs);
|
||||
|
||||
/**
|
||||
* Send notification (or indication) to any connected devices that have
|
||||
* subscribed for notification (or indication) for specified characteristic.
|
||||
*
|
||||
* @param chr_val_handle Characteristic value handle
|
||||
*/
|
||||
void ble_gatts_chr_updated(uint16_t chr_val_handle);
|
||||
|
||||
/**
|
||||
* Retrieves the attribute handle associated with a local GATT service.
|
||||
*
|
||||
* @param uuid The UUID of the service to look up.
|
||||
* @param out_handle On success, populated with the handle of the
|
||||
* service attribute. Pass null if you don't
|
||||
* need this value.
|
||||
*
|
||||
* @return 0 on success;
|
||||
* BLE_HS_ENOENT if the specified service could
|
||||
* not be found.
|
||||
*/
|
||||
int ble_gatts_find_svc(const ble_uuid_t *uuid, uint16_t *out_handle);
|
||||
|
||||
/**
|
||||
* Retrieves the pair of attribute handles associated with a local GATT
|
||||
* characteristic.
|
||||
*
|
||||
* @param svc_uuid The UUID of the parent service.
|
||||
* @param chr_uuid The UUID of the characteristic to look up.
|
||||
* @param out_def_handle On success, populated with the handle
|
||||
* of the characteristic definition attribute.
|
||||
* Pass null if you don't need this value.
|
||||
* @param out_val_handle On success, populated with the handle
|
||||
* of the characteristic value attribute.
|
||||
* Pass null if you don't need this value.
|
||||
*
|
||||
* @return 0 on success;
|
||||
* BLE_HS_ENOENT if the specified service or
|
||||
* characteristic could not be found.
|
||||
*/
|
||||
int ble_gatts_find_chr(const ble_uuid_t *svc_uuid, const ble_uuid_t *chr_uuid,
|
||||
uint16_t *out_def_handle, uint16_t *out_val_handle);
|
||||
|
||||
/**
|
||||
* Retrieves the attribute handle associated with a local GATT descriptor.
|
||||
*
|
||||
* @param svc_uuid The UUID of the grandparent service.
|
||||
* @param chr_uuid The UUID of the parent characteristic.
|
||||
* @param dsc_uuid The UUID of the descriptor ro look up.
|
||||
* @param out_handle On success, populated with the handle
|
||||
* of the descriptor attribute. Pass null if
|
||||
* you don't need this value.
|
||||
*
|
||||
* @return 0 on success;
|
||||
* BLE_HS_ENOENT if the specified service,
|
||||
* characteristic, or descriptor could not be
|
||||
* found.
|
||||
*/
|
||||
int ble_gatts_find_dsc(const ble_uuid_t *svc_uuid, const ble_uuid_t *chr_uuid,
|
||||
const ble_uuid_t *dsc_uuid, uint16_t *out_dsc_handle);
|
||||
|
||||
typedef void (*ble_gatt_svc_foreach_fn)(const struct ble_gatt_svc_def *svc,
|
||||
uint16_t handle,
|
||||
uint16_t end_group_handle,
|
||||
void *arg);
|
||||
|
||||
/**
|
||||
* Prints dump of local GATT database. This is useful to log local state of
|
||||
* database in human readable form.
|
||||
*/
|
||||
void ble_gatts_show_local(void);
|
||||
|
||||
/**
|
||||
* Resets the GATT server to its initial state. On success, this function
|
||||
* removes all supported services, characteristics, and descriptors. This
|
||||
* function requires that:
|
||||
* o No peers are connected, and
|
||||
* o No GAP operations are active (advertise, discover, or connect).
|
||||
*
|
||||
* @return 0 on success;
|
||||
* BLE_HS_EBUSY if the GATT server could not be
|
||||
* reset due to existing connections or active
|
||||
* GAP procedures.
|
||||
*/
|
||||
int ble_gatts_reset(void);
|
||||
|
||||
/**
|
||||
* Makes all registered services available to peers. This function gets called
|
||||
* automatically by the NimBLE host on startup; manual calls are only necessary
|
||||
* for replacing the set of supported services with a new one. This function
|
||||
* requires that:
|
||||
* o No peers are connected, and
|
||||
* o No GAP operations are active (advertise, discover, or connect).
|
||||
*
|
||||
* @return 0 on success;
|
||||
* A BLE host core return code on unexpected
|
||||
* error.
|
||||
*/
|
||||
int ble_gatts_start(void);
|
||||
|
||||
/**
|
||||
* Resets the GATT configuration parameters and deallocates the memory of attributes.
|
||||
*
|
||||
*/
|
||||
void ble_gatts_stop(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif
|
||||
392
lib/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_hs.h
Normal file
392
lib/NimBLE-Arduino/src/nimble/nimble/host/include/host/ble_hs.h
Normal file
@@ -0,0 +1,392 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef H_BLE_HS_
|
||||
#define H_BLE_HS_
|
||||
|
||||
/**
|
||||
* @brief Bluetooth Host
|
||||
* @defgroup bt_host Bluetooth Host
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "nimble/nimble/include/nimble/hci_common.h"
|
||||
#include "ble_att.h"
|
||||
#include "ble_eddystone.h"
|
||||
#include "ble_gap.h"
|
||||
#include "ble_gatt.h"
|
||||
#include "ble_hs_adv.h"
|
||||
#include "ble_hs_id.h"
|
||||
#include "ble_hs_hci.h"
|
||||
#include "ble_hs_log.h"
|
||||
#include "ble_hs_mbuf.h"
|
||||
#include "ble_hs_stop.h"
|
||||
#include "ble_ibeacon.h"
|
||||
#include "ble_l2cap.h"
|
||||
#include "ble_sm.h"
|
||||
#include "ble_store.h"
|
||||
#include "ble_uuid.h"
|
||||
#include "nimble/nimble/include/nimble/nimble_npl.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define BLE_HS_FOREVER INT32_MAX
|
||||
|
||||
/** Connection handle not present */
|
||||
#define BLE_HS_CONN_HANDLE_NONE 0xffff
|
||||
|
||||
/**
|
||||
* @brief Bluetooth Host Error Code
|
||||
* @defgroup bt_host_err Bluetooth Host Error Code
|
||||
*
|
||||
* Defines error codes returned by Bluetooth host. If error comes from specific
|
||||
* component (eg L2CAP or Security Manager) it is shifted by base allowing to
|
||||
* identify component.
|
||||
* @{
|
||||
*/
|
||||
|
||||
#define BLE_HS_EAGAIN 1
|
||||
#define BLE_HS_EALREADY 2
|
||||
#define BLE_HS_EINVAL 3
|
||||
#define BLE_HS_EMSGSIZE 4
|
||||
#define BLE_HS_ENOENT 5
|
||||
#define BLE_HS_ENOMEM 6
|
||||
#define BLE_HS_ENOTCONN 7
|
||||
#define BLE_HS_ENOTSUP 8
|
||||
#define BLE_HS_EAPP 9
|
||||
#define BLE_HS_EBADDATA 10
|
||||
#define BLE_HS_EOS 11
|
||||
#define BLE_HS_ECONTROLLER 12
|
||||
#define BLE_HS_ETIMEOUT 13
|
||||
#define BLE_HS_EDONE 14
|
||||
#define BLE_HS_EBUSY 15
|
||||
#define BLE_HS_EREJECT 16
|
||||
#define BLE_HS_EUNKNOWN 17
|
||||
#define BLE_HS_EROLE 18
|
||||
#define BLE_HS_ETIMEOUT_HCI 19
|
||||
#define BLE_HS_ENOMEM_EVT 20
|
||||
#define BLE_HS_ENOADDR 21
|
||||
#define BLE_HS_ENOTSYNCED 22
|
||||
#define BLE_HS_EAUTHEN 23
|
||||
#define BLE_HS_EAUTHOR 24
|
||||
#define BLE_HS_EENCRYPT 25
|
||||
#define BLE_HS_EENCRYPT_KEY_SZ 26
|
||||
#define BLE_HS_ESTORE_CAP 27
|
||||
#define BLE_HS_ESTORE_FAIL 28
|
||||
#define BLE_HS_EPREEMPTED 29
|
||||
#define BLE_HS_EDISABLED 30
|
||||
#define BLE_HS_ESTALLED 31
|
||||
|
||||
/** Error base for ATT errors */
|
||||
#define BLE_HS_ERR_ATT_BASE 0x100
|
||||
|
||||
/** Converts error to ATT base */
|
||||
#define BLE_HS_ATT_ERR(x) ((x) ? BLE_HS_ERR_ATT_BASE + (x) : 0)
|
||||
|
||||
/** Error base for HCI errors */
|
||||
#define BLE_HS_ERR_HCI_BASE 0x200
|
||||
|
||||
/** Converts error to HCI base */
|
||||
#define BLE_HS_HCI_ERR(x) ((x) ? BLE_HS_ERR_HCI_BASE + (x) : 0)
|
||||
|
||||
/** Error base for L2CAP errors */
|
||||
#define BLE_HS_ERR_L2C_BASE 0x300
|
||||
|
||||
/** Converts error to L2CAP base */
|
||||
#define BLE_HS_L2C_ERR(x) ((x) ? BLE_HS_ERR_L2C_BASE + (x) : 0)
|
||||
|
||||
/** Error base for local Security Manager errors */
|
||||
#define BLE_HS_ERR_SM_US_BASE 0x400
|
||||
|
||||
/** Converts error to local Security Manager base */
|
||||
#define BLE_HS_SM_US_ERR(x) ((x) ? BLE_HS_ERR_SM_US_BASE + (x) : 0)
|
||||
|
||||
/** Error base for remote (peer) Security Manager errors */
|
||||
#define BLE_HS_ERR_SM_PEER_BASE 0x500
|
||||
|
||||
/** Converts error to remote (peer) Security Manager base */
|
||||
#define BLE_HS_SM_PEER_ERR(x) ((x) ? BLE_HS_ERR_SM_PEER_BASE + (x) : 0)
|
||||
|
||||
/** Error base for hardware errors */
|
||||
#define BLE_HS_ERR_HW_BASE 0x600
|
||||
|
||||
/** Converts error to hardware error base */
|
||||
#define BLE_HS_HW_ERR(x) (BLE_HS_ERR_HW_BASE + (x))
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Bluetooth Host Configuration
|
||||
* @defgroup bt_host_conf Bluetooth Host Configuration
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Local Input-Output capabilities of device
|
||||
* @defgroup bt_host_io_local Local Input-Output capabilities of device
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/** DisplayOnly IO capability */
|
||||
#define BLE_HS_IO_DISPLAY_ONLY 0x00
|
||||
|
||||
/** DisplayYesNo IO capability */
|
||||
#define BLE_HS_IO_DISPLAY_YESNO 0x01
|
||||
|
||||
/** KeyboardOnly IO capability */
|
||||
#define BLE_HS_IO_KEYBOARD_ONLY 0x02
|
||||
|
||||
/** NoInputNoOutput IO capability */
|
||||
#define BLE_HS_IO_NO_INPUT_OUTPUT 0x03
|
||||
|
||||
/** KeyboardDisplay Only IO capability */
|
||||
#define BLE_HS_IO_KEYBOARD_DISPLAY 0x04
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/** @brief Stack reset callback
|
||||
*
|
||||
* @param reason Reason code for reset
|
||||
*/
|
||||
typedef void ble_hs_reset_fn(int reason);
|
||||
|
||||
|
||||
/** @brief Stack sync callback */
|
||||
typedef void ble_hs_sync_fn(void);
|
||||
|
||||
/** @brief Bluetooth Host main configuration structure
|
||||
*
|
||||
* Those can be used by application to configure stack.
|
||||
*
|
||||
* The only reason Security Manager (sm_ members) is configurable at runtime is
|
||||
* to simplify security testing. Defaults for those are configured by selecting
|
||||
* proper options in application's syscfg.
|
||||
*/
|
||||
struct ble_hs_cfg {
|
||||
/**
|
||||
* An optional callback that gets executed upon registration of each GATT
|
||||
* resource (service, characteristic, or descriptor).
|
||||
*/
|
||||
ble_gatt_register_fn *gatts_register_cb;
|
||||
|
||||
/**
|
||||
* An optional argument that gets passed to the GATT registration
|
||||
* callback.
|
||||
*/
|
||||
void *gatts_register_arg;
|
||||
|
||||
/** Security Manager Local Input Output Capabilities */
|
||||
uint8_t sm_io_cap;
|
||||
|
||||
/** @brief Security Manager OOB flag
|
||||
*
|
||||
* If set proper flag in Pairing Request/Response will be set.
|
||||
*/
|
||||
unsigned sm_oob_data_flag:1;
|
||||
|
||||
/** @brief Security Manager Bond flag
|
||||
*
|
||||
* If set proper flag in Pairing Request/Response will be set. This results
|
||||
* in storing keys distributed during bonding.
|
||||
*/
|
||||
unsigned sm_bonding:1;
|
||||
|
||||
/** @brief Security Manager MITM flag
|
||||
*
|
||||
* If set proper flag in Pairing Request/Response will be set. This results
|
||||
* in requiring Man-In-The-Middle protection when pairing.
|
||||
*/
|
||||
unsigned sm_mitm:1;
|
||||
|
||||
/** @brief Security Manager Secure Connections flag
|
||||
*
|
||||
* If set proper flag in Pairing Request/Response will be set. This results
|
||||
* in using LE Secure Connections for pairing if also supported by remote
|
||||
* device. Fallback to legacy pairing if not supported by remote.
|
||||
*/
|
||||
unsigned sm_sc:1;
|
||||
|
||||
/** @brief Security Manager Key Press Notification flag
|
||||
*
|
||||
* Currently unsupported and should not be set.
|
||||
*/
|
||||
unsigned sm_keypress:1;
|
||||
|
||||
/** @brief Security Manager Local Key Distribution Mask */
|
||||
uint8_t sm_our_key_dist;
|
||||
|
||||
/** @brief Security Manager Remote Key Distribution Mask */
|
||||
uint8_t sm_their_key_dist;
|
||||
|
||||
/** @brief Stack reset callback
|
||||
*
|
||||
* This callback is executed when the host resets itself and the controller
|
||||
* due to fatal error.
|
||||
*/
|
||||
ble_hs_reset_fn *reset_cb;
|
||||
|
||||
/** @brief Stack sync callback
|
||||
*
|
||||
* This callback is executed when the host and controller become synced.
|
||||
* This happens at startup and after a reset.
|
||||
*/
|
||||
ble_hs_sync_fn *sync_cb;
|
||||
|
||||
/* XXX: These need to go away. Instead, the nimble host package should
|
||||
* require the host-store API (not yet implemented)..
|
||||
*/
|
||||
/** Storage Read callback handles read of security material */
|
||||
ble_store_read_fn *store_read_cb;
|
||||
|
||||
/** Storage Write callback handles write of security material */
|
||||
ble_store_write_fn *store_write_cb;
|
||||
|
||||
/** Storage Delete callback handles deletion of security material */
|
||||
ble_store_delete_fn *store_delete_cb;
|
||||
|
||||
/** @brief Storage Status callback.
|
||||
*
|
||||
* This callback gets executed when a persistence operation cannot be
|
||||
* performed or a persistence failure is imminent. For example, if is
|
||||
* insufficient storage capacity for a record to be persisted, this
|
||||
* function gets called to give the application the opportunity to make
|
||||
* room.
|
||||
*/
|
||||
ble_store_status_fn *store_status_cb;
|
||||
|
||||
/** An optional argument that gets passed to the storage status callback. */
|
||||
void *store_status_arg;
|
||||
};
|
||||
|
||||
extern struct ble_hs_cfg ble_hs_cfg;
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Indicates whether the host is enabled. The host is enabled if it is
|
||||
* starting or fully started. It is disabled if it is stopping or stopped.
|
||||
*
|
||||
* @return 1 if the host is enabled;
|
||||
* 0 if the host is disabled.
|
||||
*/
|
||||
int ble_hs_is_enabled(void);
|
||||
|
||||
/**
|
||||
* Indicates whether the host has synchronized with the controller.
|
||||
* Synchronization must occur before any host procedures can be performed.
|
||||
*
|
||||
* @return 1 if the host and controller are in sync;
|
||||
* 0 if the host and controller are out of sync.
|
||||
*/
|
||||
int ble_hs_synced(void);
|
||||
|
||||
/**
|
||||
* Synchronizes the host with the controller by sending a sequence of HCI
|
||||
* commands. This function must be called before any other host functionality
|
||||
* is used, but it must be called after both the host and controller are
|
||||
* initialized. Typically, the host-parent-task calls this function at the top
|
||||
* of its task routine. This function must only be called in the host parent
|
||||
* task. A safe alternative for starting the stack from any task is to call
|
||||
* `ble_hs_sched_start()`.
|
||||
*
|
||||
* If the host fails to synchronize with the controller (if the controller is
|
||||
* not fully booted, for example), the host will attempt to resynchronize every
|
||||
* 100 ms. For this reason, an error return code is not necessarily fatal.
|
||||
*
|
||||
* @return 0 on success; nonzero on error.
|
||||
*/
|
||||
int ble_hs_start(void);
|
||||
|
||||
/**
|
||||
* Enqueues a host start event to the default event queue. The actual host
|
||||
* startup is performed in the host parent task, but using the default queue
|
||||
* here ensures the event won't run until the end of main() when this is
|
||||
* called during system initialization. This allows the application to
|
||||
* configure the host package in the meantime.
|
||||
*
|
||||
* If auto-start is disabled, the application should use this function to start
|
||||
* the BLE stack. This function can be called at any time as long as the host
|
||||
* is stopped. When the host successfully starts, the application is notified
|
||||
* via the ble_hs_cfg.sync_cb callback.
|
||||
*/
|
||||
void ble_hs_sched_start(void);
|
||||
|
||||
/**
|
||||
* Causes the host to reset the NimBLE stack as soon as possible. The
|
||||
* application is notified when the reset occurs via the host reset callback.
|
||||
*
|
||||
* @param reason The host error code that gets passed to the reset callback.
|
||||
*/
|
||||
void ble_hs_sched_reset(int reason);
|
||||
|
||||
/**
|
||||
* Designates the specified event queue for NimBLE host work. By default, the
|
||||
* host uses the default event queue and runs in the main task. This function
|
||||
* is useful if you want the host to run in a different task.
|
||||
*
|
||||
* @param evq The event queue to use for host work.
|
||||
*/
|
||||
void ble_hs_evq_set(struct ble_npl_eventq *evq);
|
||||
|
||||
/**
|
||||
* Initializes the NimBLE host. This function must be called before the OS is
|
||||
* started. The NimBLE stack requires an application task to function. One
|
||||
* application task in particular is designated as the "host parent task". In
|
||||
* addition to application-specific work, the host parent task does work for
|
||||
* NimBLE by processing events generated by the host.
|
||||
*/
|
||||
void ble_hs_init(void);
|
||||
|
||||
/**
|
||||
* Deinitializes the NimBLE host. This function must be called after the
|
||||
* NimBLE host stop procedure is complete.
|
||||
*/
|
||||
void ble_hs_deinit(void);
|
||||
|
||||
/**
|
||||
* @brief Called when the system is shutting down. Stops the BLE host.
|
||||
*
|
||||
* @param reason The reason for the shutdown. One of the
|
||||
* HAL_RESET_[...] codes or an
|
||||
* implementation-defined value.
|
||||
*
|
||||
* @return SYSDOWN_IN_PROGRESS.
|
||||
*/
|
||||
int ble_hs_shutdown(int reason);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef H_BLE_HS_ADV_
|
||||
#define H_BLE_HS_ADV_
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "ble_uuid.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define BLE_HS_ADV_MAX_SZ BLE_HCI_MAX_ADV_DATA_LEN
|
||||
|
||||
/** Max field payload size (account for 2-byte header). */
|
||||
#define BLE_HS_ADV_MAX_FIELD_SZ (BLE_HS_ADV_MAX_SZ - 2)
|
||||
|
||||
struct ble_hs_adv_field {
|
||||
uint8_t length;
|
||||
uint8_t type;
|
||||
uint8_t value[0];
|
||||
};
|
||||
|
||||
typedef int (* ble_hs_adv_parse_func_t) (const struct ble_hs_adv_field *,
|
||||
void *);
|
||||
|
||||
struct ble_hs_adv_fields {
|
||||
/*** 0x01 - Flags. */
|
||||
uint8_t flags;
|
||||
|
||||
/*** 0x02,0x03 - 16-bit service class UUIDs. */
|
||||
const ble_uuid16_t *uuids16;
|
||||
uint8_t num_uuids16;
|
||||
unsigned uuids16_is_complete:1;
|
||||
|
||||
/*** 0x04,0x05 - 32-bit service class UUIDs. */
|
||||
const ble_uuid32_t *uuids32;
|
||||
uint8_t num_uuids32;
|
||||
unsigned uuids32_is_complete:1;
|
||||
|
||||
/*** 0x06,0x07 - 128-bit service class UUIDs. */
|
||||
const ble_uuid128_t *uuids128;
|
||||
uint8_t num_uuids128;
|
||||
unsigned uuids128_is_complete:1;
|
||||
|
||||
/*** 0x08,0x09 - Local name. */
|
||||
const uint8_t *name;
|
||||
uint8_t name_len;
|
||||
unsigned name_is_complete:1;
|
||||
|
||||
/*** 0x0a - Tx power level. */
|
||||
int8_t tx_pwr_lvl;
|
||||
unsigned tx_pwr_lvl_is_present:1;
|
||||
|
||||
/*** 0x0d - Slave connection interval range. */
|
||||
const uint8_t *slave_itvl_range;
|
||||
|
||||
/*** 0x16 - Service data - 16-bit UUID. */
|
||||
const uint8_t *svc_data_uuid16;
|
||||
uint8_t svc_data_uuid16_len;
|
||||
|
||||
/*** 0x17 - Public target address. */
|
||||
const uint8_t *public_tgt_addr;
|
||||
uint8_t num_public_tgt_addrs;
|
||||
|
||||
/*** 0x19 - Appearance. */
|
||||
uint16_t appearance;
|
||||
unsigned appearance_is_present:1;
|
||||
|
||||
/*** 0x1a - Advertising interval. */
|
||||
uint16_t adv_itvl;
|
||||
unsigned adv_itvl_is_present:1;
|
||||
|
||||
/*** 0x20 - Service data - 32-bit UUID. */
|
||||
const uint8_t *svc_data_uuid32;
|
||||
uint8_t svc_data_uuid32_len;
|
||||
|
||||
/*** 0x21 - Service data - 128-bit UUID. */
|
||||
const uint8_t *svc_data_uuid128;
|
||||
uint8_t svc_data_uuid128_len;
|
||||
|
||||
/*** 0x24 - URI. */
|
||||
const uint8_t *uri;
|
||||
uint8_t uri_len;
|
||||
|
||||
/*** 0xff - Manufacturer specific data. */
|
||||
const uint8_t *mfg_data;
|
||||
uint8_t mfg_data_len;
|
||||
};
|
||||
|
||||
#define BLE_HS_ADV_TYPE_FLAGS 0x01
|
||||
#define BLE_HS_ADV_TYPE_INCOMP_UUIDS16 0x02
|
||||
#define BLE_HS_ADV_TYPE_COMP_UUIDS16 0x03
|
||||
#define BLE_HS_ADV_TYPE_INCOMP_UUIDS32 0x04
|
||||
#define BLE_HS_ADV_TYPE_COMP_UUIDS32 0x05
|
||||
#define BLE_HS_ADV_TYPE_INCOMP_UUIDS128 0x06
|
||||
#define BLE_HS_ADV_TYPE_COMP_UUIDS128 0x07
|
||||
#define BLE_HS_ADV_TYPE_INCOMP_NAME 0x08
|
||||
#define BLE_HS_ADV_TYPE_COMP_NAME 0x09
|
||||
#define BLE_HS_ADV_TYPE_TX_PWR_LVL 0x0a
|
||||
#define BLE_HS_ADV_TYPE_SLAVE_ITVL_RANGE 0x12
|
||||
#define BLE_HS_ADV_TYPE_SOL_UUIDS16 0x14
|
||||
#define BLE_HS_ADV_TYPE_SOL_UUIDS128 0x15
|
||||
#define BLE_HS_ADV_TYPE_SVC_DATA_UUID16 0x16
|
||||
#define BLE_HS_ADV_TYPE_PUBLIC_TGT_ADDR 0x17
|
||||
#define BLE_HS_ADV_TYPE_RANDOM_TGT_ADDR 0x18
|
||||
#define BLE_HS_ADV_TYPE_APPEARANCE 0x19
|
||||
#define BLE_HS_ADV_TYPE_ADV_ITVL 0x1a
|
||||
#define BLE_HS_ADV_TYPE_SVC_DATA_UUID32 0x20
|
||||
#define BLE_HS_ADV_TYPE_SVC_DATA_UUID128 0x21
|
||||
#define BLE_HS_ADV_TYPE_URI 0x24
|
||||
#define BLE_HS_ADV_TYPE_MESH_PROV 0x29
|
||||
#define BLE_HS_ADV_TYPE_MESH_MESSAGE 0x2a
|
||||
#define BLE_HS_ADV_TYPE_MESH_BEACON 0x2b
|
||||
#define BLE_HS_ADV_TYPE_MFG_DATA 0xff
|
||||
|
||||
#define BLE_HS_ADV_FLAGS_LEN 1
|
||||
#define BLE_HS_ADV_F_DISC_LTD 0x01
|
||||
#define BLE_HS_ADV_F_DISC_GEN 0x02
|
||||
#define BLE_HS_ADV_F_BREDR_UNSUP 0x04
|
||||
|
||||
#define BLE_HS_ADV_TX_PWR_LVL_LEN 1
|
||||
|
||||
/**
|
||||
* Set the tx_pwr_lvl field to this if you want the stack to fill in the tx
|
||||
* power level field.
|
||||
*/
|
||||
#define BLE_HS_ADV_TX_PWR_LVL_AUTO (-128)
|
||||
|
||||
#define BLE_HS_ADV_SLAVE_ITVL_RANGE_LEN 4
|
||||
|
||||
#define BLE_HS_ADV_SVC_DATA_UUID16_MIN_LEN 2
|
||||
|
||||
#define BLE_HS_ADV_PUBLIC_TGT_ADDR_ENTRY_LEN 6
|
||||
|
||||
#define BLE_HS_ADV_APPEARANCE_LEN 2
|
||||
|
||||
#define BLE_HS_ADV_ADV_ITVL_LEN 2
|
||||
|
||||
#define BLE_HS_ADV_SVC_DATA_UUID32_MIN_LEN 4
|
||||
|
||||
#define BLE_HS_ADV_SVC_DATA_UUID128_MIN_LEN 16
|
||||
|
||||
int ble_hs_adv_set_fields_mbuf(const struct ble_hs_adv_fields *adv_fields,
|
||||
struct os_mbuf *om);
|
||||
|
||||
int ble_hs_adv_set_fields(const struct ble_hs_adv_fields *adv_fields,
|
||||
uint8_t *dst, uint8_t *dst_len, uint8_t max_len);
|
||||
|
||||
int ble_hs_adv_parse_fields(struct ble_hs_adv_fields *adv_fields,
|
||||
const uint8_t *src, uint8_t src_len);
|
||||
|
||||
int ble_hs_adv_parse(const uint8_t *data, uint8_t length,
|
||||
ble_hs_adv_parse_func_t func, void *user_data);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef H_BLE_HS_HCI_
|
||||
#define H_BLE_HS_HCI_
|
||||
|
||||
/**
|
||||
* @brief Bluetooth Host HCI utils
|
||||
* @defgroup bt_host_hci Bluetooth Host HCI utils
|
||||
* @ingroup bt_host
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Queries the controller for the channel map used with the specified
|
||||
* connection. The channel map is represented as an array of five bytes, with
|
||||
* each bit corresponding to an individual channel. The array is interpreted
|
||||
* as little-endian, such that:
|
||||
* map[0] & 0x01 --> Channel 0.
|
||||
* map[0] & 0x02 --> Channel 1.
|
||||
* ...
|
||||
* map[1] & 0x01 --> Channel 8.
|
||||
*
|
||||
* As there are 37 channels, only the first 37 bits get written.
|
||||
*
|
||||
* If a bit is 1, the corresponding channel is used. Otherwise, the channel is
|
||||
* unused.
|
||||
*
|
||||
* @param conn_handle The handle of the connection whose channel map
|
||||
* is being read.
|
||||
* @param out_chan_map On success, the retrieved channel map gets
|
||||
* written here. This buffer must have a size
|
||||
* >= 5 bytes.
|
||||
*
|
||||
* @return 0 on success;
|
||||
* A BLE host HCI return code if the controller
|
||||
* rejected the request;
|
||||
* A BLE host core return code on unexpected
|
||||
* error.
|
||||
*/
|
||||
int ble_hs_hci_read_chan_map(uint16_t conn_handle, uint8_t *out_chan_map);
|
||||
|
||||
/**
|
||||
* Instructs the controller to use the specified channel map. The channel map
|
||||
* is represented as an array of five bytes, with each bit corresponding to an
|
||||
* individual channel. The array is interpreted as little-endian, such that:
|
||||
* map[0] & 0x01 --> Channel 0.
|
||||
* map[0] & 0x02 --> Channel 1.
|
||||
* ...
|
||||
* map[1] & 0x01 --> Channel 8.
|
||||
*
|
||||
* As there are 37 channels, only the first 37 bits should be written are used.
|
||||
*
|
||||
* If a bit is 1, the corresponding channel can be used. Otherwise, the
|
||||
* channel should not be used.
|
||||
*
|
||||
* @param chan_map The channel map to configure. This buffer
|
||||
* should have a size of 5 bytes.
|
||||
*
|
||||
* @return 0 on success;
|
||||
* A BLE host HCI return code if the controller
|
||||
* rejected the request;
|
||||
* A BLE host core return code on unexpected
|
||||
* error.
|
||||
*/
|
||||
int ble_hs_hci_set_chan_class(const uint8_t *chan_map);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif
|
||||
@@ -0,0 +1,132 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
|
||||
#ifndef H_BLE_HS_ID_
|
||||
#define H_BLE_HS_ID_
|
||||
|
||||
/**
|
||||
* @brief Bluetooth Host Identity
|
||||
* @defgroup bt_host_id Bluetooth Host Identity
|
||||
* @ingroup bt_host
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <inttypes.h>
|
||||
#include "nimble/nimble/include/nimble/ble.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Generates a new random address. This function does not configure the device
|
||||
* with the new address; the caller can use the address in subsequent
|
||||
* operations.
|
||||
*
|
||||
* @param nrpa The type of random address to generate:
|
||||
* 0: static
|
||||
* 1: non-resolvable private
|
||||
* @param out_addr On success, the generated address gets written
|
||||
* here.
|
||||
*
|
||||
* @return 0 on success; nonzero on failure.
|
||||
*/
|
||||
int ble_hs_id_gen_rnd(int nrpa, ble_addr_t *out_addr);
|
||||
|
||||
/**
|
||||
* Sets the device's random address. The address type (static vs.
|
||||
* non-resolvable private) is inferred from the most-significant byte of the
|
||||
* address. The address is specified in host byte order (little-endian!).
|
||||
*
|
||||
* @param rnd_addr The random address to set.
|
||||
*
|
||||
* @return 0 on success;
|
||||
* BLE_HS_EINVAL if the specified address is not a
|
||||
* valid static random or non-resolvable
|
||||
* private address.
|
||||
* Other nonzero on error.
|
||||
*/
|
||||
int ble_hs_id_set_rnd(const uint8_t *rnd_addr);
|
||||
|
||||
/**
|
||||
* Retrieves one of the device's identity addresses. The device can have two
|
||||
* identity addresses: one public and one random. The id_addr_type argument
|
||||
* specifies which of these two addresses to retrieve.
|
||||
*
|
||||
* @param id_addr_type The type of identity address to retrieve.
|
||||
* Valid values are:
|
||||
* o BLE_ADDR_PUBLIC
|
||||
* o BLE_ADDR_RANDOM
|
||||
* @param out_id_addr On success, the requested identity address is
|
||||
* copied into this buffer. The buffer must
|
||||
* be at least six bytes in size. Pass NULL
|
||||
* if you do not require this information.
|
||||
* @param out_is_nrpa On success, the pointed-to value indicates
|
||||
* whether the retrieved address is a
|
||||
* non-resolvable private address. Pass NULL
|
||||
* if you do not require this information.
|
||||
*
|
||||
* @return 0 on success;
|
||||
* BLE_HS_EINVAL if an invalid address type was
|
||||
* specified;
|
||||
* BLE_HS_ENOADDR if the device does not have an
|
||||
* identity address of the requested type;
|
||||
* Other BLE host core code on error.
|
||||
*/
|
||||
int ble_hs_id_copy_addr(uint8_t id_addr_type, uint8_t *out_id_addr,
|
||||
int *out_is_nrpa);
|
||||
|
||||
/**
|
||||
* Determines the best address type to use for automatic address type
|
||||
* resolution. Calculation of the best address type is done as follows:
|
||||
*
|
||||
* if privacy requested:
|
||||
* if we have a random static address:
|
||||
* --> RPA with static random ID
|
||||
* else
|
||||
* --> RPA with public ID
|
||||
* end
|
||||
* else
|
||||
* if we have a random static address:
|
||||
* --> random static address
|
||||
* else
|
||||
* --> public address
|
||||
* end
|
||||
* end
|
||||
*
|
||||
* @param privacy (0/1) Whether to use a private address.
|
||||
* @param out_addr_type On success, the "own addr type" code gets
|
||||
* written here.
|
||||
*
|
||||
* @return 0 if an address type was successfully inferred.
|
||||
* BLE_HS_ENOADDR if the device does not have a
|
||||
* suitable address.
|
||||
* Other BLE host core code on error.
|
||||
*/
|
||||
int ble_hs_id_infer_auto(int privacy, uint8_t *out_addr_type);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @}
|
||||
*/
|
||||
|
||||
#endif
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user