Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion fsutils/passwd/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,14 @@
if(CONFIG_FSUTILS_PASSWD)
set(CSRCS)

list(APPEND CSRCS passwd_verify.c passwd_find.c passwd_encrypt.c)
list(
APPEND
CSRCS
passwd_verify.c
passwd_find.c
passwd_encrypt.c
passwd_base64.c
passwd_pbkdf2.c)

if(NOT CONFIG_FSUTILS_PASSWD_READONLY)
list(
Expand Down
33 changes: 17 additions & 16 deletions fsutils/passwd/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,15 @@
config FSUTILS_PASSWD
bool "Password file support"
default n
select CRYPTO
select ALLOW_BSD_COMPONENTS
select CRYPTO_CRYPTODEV

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's use depends on or skip PBKDF2-HMAC-SHA256 if crypto isn't enabled

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we make NSH_CONSOLE_LOGIN depend on FSUTILS_PASSWD / cryptodev so login always uses PBKDF2, and treat NSH_LOGIN_FIXED as an explicit opt-in for legacy boards only?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we keep something like this:
image

Because if we use "depends on," the user might go for the fixed password most of the time, which is not recommended.

---help---
Enables support for /etc/passwd file access routines
Enables support for /etc/passwd file access routines.

NOTE: Password hashes use PBKDF2-HMAC-SHA256 (modular crypt format).
Existing TEA-encrypted /etc/passwd entries are NOT compatible and
must be regenerated.

if FSUTILS_PASSWD

Expand All @@ -23,20 +30,14 @@ config FSUTILS_PASSWD_IOBUFFER_SIZE
int "Allocated I/O buffer size"
default 512

config FSUTILS_PASSWD_KEY1
hex "Encryption key value 1"
default 0x12345678

config FSUTILS_PASSWD_KEY2
hex "Encryption key value 2"
default 0x9abcdef0

config FSUTILS_PASSWD_KEY3
hex "Encryption key value 3"
default 0x12345678

config FSUTILS_PASSWD_KEY4
hex "Encryption key value 4"
default 0x9abcdef0
config FSUTILS_PASSWD_PBKDF2_ITERATIONS

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

remove indent

int "Default PBKDF2 iteration count for new passwords"
default 10000
range 1000 200000
---help---
Number of PBKDF2-HMAC-SHA256 iterations applied when setting a new
password. Higher values slow brute-force attacks but also increase
login latency on low-MHz MCUs. The iteration count is stored in each
hash string, so changing this option only affects newly-set passwords.

endif # FSUTILS_PASSWD
3 changes: 2 additions & 1 deletion fsutils/passwd/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ include $(APPDIR)/Make.defs
# Password file access library

ifeq ($(CONFIG_FSUTILS_PASSWD),y)
CSRCS += passwd_verify.c passwd_find.c passwd_encrypt.c
CSRCS += passwd_verify.c passwd_find.c passwd_encrypt.c passwd_base64.c
CSRCS += passwd_pbkdf2.c
ifneq ($(CONFIG_FSUTILS_PASSWD_READONLY),y)
CSRCS += passwd_adduser.c passwd_deluser.c passwd_update.c passwd_append.c
CSRCS += passwd_delete.c passwd_lock.c
Expand Down
26 changes: 14 additions & 12 deletions fsutils/passwd/passwd.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,17 +36,18 @@
* Pre-processor Definitions
****************************************************************************/

#define MAX_ENCRYPTED 48 /* Maximum size of a password (encrypted, ASCII) */
#define MAX_USERNAME 48 /* Maximum size of a username */
#define MAX_RECORD (MAX_USERNAME + MAX_ENCRYPTED + 1)
/* MCF format: $pbkdf2-sha256$<iter>$<salt>$<hash> */

/* The TEA incryption algorithm generates 8 bytes of encrypted data per
* 8 bytes of unencrypted data. The encrypted presentation is base64 which
* is 8-bits of ASCII for each 6 bits of data. That is a 3-to-4 expansion
* ratio. MAX_ENCRYPTED must be a multiple of 8 bytes.
*/
#define PASSWD_MCF_PREFIX "$pbkdf2-sha256$"
#define PASSWD_SALT_BYTES 16
#define PASSWD_HASH_BYTES 32

#define MAX_PASSWORD (3 * MAX_ENCRYPTED / 4)
/* 15 + 6 + 1 + 22 + 1 + 43 = 88 bytes for default parameters */

#define MAX_ENCRYPTED 96
#define MAX_USERNAME 48
#define MAX_RECORD (MAX_USERNAME + MAX_ENCRYPTED + 1)
#define MAX_PASSWORD 256

/****************************************************************************
* Public Types
Expand All @@ -55,7 +56,7 @@
struct passwd_s
{
off_t offset; /* File offset (start of record) */
char encrypted[MAX_ENCRYPTED + 1]; /* Encrtyped password in file */
char encrypted[MAX_ENCRYPTED + 1]; /* Password hash in file */
};

/****************************************************************************
Expand Down Expand Up @@ -94,10 +95,11 @@ void passwd_unlock(FAR sem_t *sem);
* Name: passwd_encrypt
*
* Description:
* Encrypt a password. Currently uses the Tiny Encryption Algorithm.
* Hash a password with PBKDF2-HMAC-SHA256 and encode the result in modular
* crypt format for storage in /etc/passwd.
*
* Input Parameters:
* password -- The password string to be encrypted
* password -- The password string to be hashed
*
* Returned Value:
* Zero (OK) is returned on success; a negated errno value is returned on
Expand Down
187 changes: 187 additions & 0 deletions fsutils/passwd/passwd_base64.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,187 @@
/****************************************************************************
* apps/fsutils/passwd/passwd_base64.c
*
* SPDX-License-Identifier: Apache-2.0
*
* 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.
*
****************************************************************************/

/****************************************************************************
* Included Files
****************************************************************************/

#include <nuttx/config.h>

#include <errno.h>
#include <stdint.h>

#include "passwd_base64.h"

/****************************************************************************
* Pre-processor Definitions
****************************************************************************/

/* RFC 4648 section 5 base64url alphabet (no padding). */

static const char g_base64url[] =

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

should we call netutils/codecs/base64.c?

"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";

/****************************************************************************
* Private Functions
****************************************************************************/

static int passwd_base64url_val(char c)
{
if (c >= 'A' && c <= 'Z')
{
return c - 'A';
}

if (c >= 'a' && c <= 'z')
{
return c - 'a' + 26;
}

if (c >= '0' && c <= '9')
{
return c - '0' + 52;
}

if (c == '-')
{
return 62;
}

if (c == '_')
{
return 63;
}

return -1;
}

/****************************************************************************
* Public Functions
****************************************************************************/

/****************************************************************************
* Name: passwd_base64url_encode
*
* Description:
* Encode binary data as unpadded base64url (RFC 4648 section 5).
*
****************************************************************************/

int passwd_base64url_encode(FAR const uint8_t *in, size_t inlen,
FAR char *out, size_t outlen)
{
uint32_t acc = 0;
size_t i;
size_t o = 0;
int bits = 0;

for (i = 0; i < inlen; i++)
{
acc = (acc << 8) | in[i];
bits += 8;

while (bits >= 6)
{
if (o + 1 >= outlen)
{
return -E2BIG;
}

bits -= 6;
out[o++] = g_base64url[(acc >> bits) & 0x3f];
}
}

if (bits > 0)
{
if (o + 1 >= outlen)
{
return -E2BIG;
}

out[o++] = g_base64url[(acc << (6 - bits)) & 0x3f];
}

if (o >= outlen)
{
return -E2BIG;
}

out[o] = '\0';
return OK;
}

/****************************************************************************
* Name: passwd_base64url_decode
*
* Description:
* Decode unpadded base64url (RFC 4648 section 5).
*
****************************************************************************/

int passwd_base64url_decode(FAR const char *in,
FAR uint8_t *out, size_t outmax,
FAR size_t *outlen)
{
uint32_t acc = 0;
size_t o = 0;
int bits = 0;
int v;

*outlen = 0;

while (*in != '\0')
{
if (*in == '$' || *in == ':')
{
break;
}

v = passwd_base64url_val(*in++);
if (v < 0)
{
return -EINVAL;
}

acc = (acc << 6) | (uint32_t)v;
bits += 6;

if (bits >= 8)
{
bits -= 8;
if (o >= outmax)
{
return -E2BIG;
}

out[o++] = (uint8_t)((acc >> bits) & 0xff);
}
}

if (bits >= 6)
{
return -EINVAL;
}

*outlen = o;
return OK;
}
45 changes: 45 additions & 0 deletions fsutils/passwd/passwd_base64.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
/****************************************************************************
* apps/fsutils/passwd/passwd_base64.h
*
* SPDX-License-Identifier: Apache-2.0
*
* 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 __APPS_FSUTILS_PASSWD_PASSWD_BASE64_H
#define __APPS_FSUTILS_PASSWD_PASSWD_BASE64_H

/****************************************************************************
* Included Files
****************************************************************************/

#include <nuttx/config.h>

#include <sys/types.h>
#include <stdint.h>

/****************************************************************************
* Public Function Prototypes
****************************************************************************/

int passwd_base64url_encode(FAR const uint8_t *in, size_t inlen,
FAR char *out, size_t outlen);
int passwd_base64url_decode(FAR const char *in,
FAR uint8_t *out, size_t outmax,
FAR size_t *outlen);

#endif /* __APPS_FSUTILS_PASSWD_PASSWD_BASE64_H */
Loading
Loading