2323/****************************************************************************
2424 * Description:
2525 * Host build tool that generates a NuttX /etc/passwd entry with a
26- * TEA-encrypted password hash.
26+ * TEA-encrypted password hash. This is a pure C replacement for the
27+ * former tools/mkpasswd.py, removing the Python dependency from the build.
2728 *
2829 * The encryption algorithm and base64 encoding are identical to those
2930 * used at runtime by:
6869#include <stdlib.h>
6970#include <string.h>
7071#include <errno.h>
71- #include <getopt.h>
7272#include <sys/stat.h>
7373
7474/****************************************************************************
7979
8080#define TEA_KEY_SCHEDULE_CONSTANT 0x9e3779b9u
8181
82- /* Password size limits – must match apps/fsutils/passwd/passwd.h.
83- * MAX_ENCRYPTED is the max length of the encrypted hash (ASCII chars).
84- * MAX_PASSWORD is the max length of the plaintext password.
85- */
82+ /* Password size limits – must match apps/fsutils/passwd/passwd.h */
8683
87- #define MAX_ENCRYPTED 48
88- #define MAX_PASSWORD (3 * MAX_ENCRYPTED / 4)
84+ #define MAX_ENCRYPTED 48 /* Max size of encrypted password (ASCII) */
85+ #define MAX_PASSWORD (3 * MAX_ENCRYPTED / 4) /* Max plaintext length */
86+ #define MIN_PASSWORD 8 /* Minimum plaintext length for security */
8987
90- /* Default TEA key values - must match CONFIG_FSUTILS_PASSWD_KEY1-4 defaults
88+ /* Default TEA key values – must match CONFIG_FSUTILS_PASSWD_KEY1-4 defaults
9189 * in apps/fsutils/passwd/Kconfig so that the generated hash verifies
9290 * correctly at runtime when the user has not changed the key config.
9391 */
@@ -364,20 +362,12 @@ static int mkdir_p(const char *path)
364362 if (* p == '/' )
365363 {
366364 * p = '\0' ;
367- #ifdef CONFIG_WINDOWS_NATIVE
368- mkdir (tmp );
369- #else
370365 mkdir (tmp , 0755 );
371- #endif
372366 * p = '/' ;
373367 }
374368 }
375369
376- #ifdef CONFIG_WINDOWS_NATIVE
377- mkdir (tmp );
378- #else
379370 mkdir (tmp , 0755 );
380- #endif
381371 free (tmp );
382372 return 0 ;
383373}
@@ -427,105 +417,81 @@ int main(int argc, char **argv)
427417
428418 char encrypted [MAX_ENCRYPTED + 1 ];
429419 FILE * out ;
430- int opt ;
420+ int i ;
431421 int ret ;
432422
433- static const struct option g_long_options [] =
434- {
435- { "user" , required_argument , NULL , 'u' },
436- { "password" , required_argument , NULL , 'p' },
437- { "uid" , required_argument , NULL , 'i' },
438- { "gid" , required_argument , NULL , 'g' },
439- { "home" , required_argument , NULL , 'd' },
440- { "key1" , required_argument , NULL , '1' },
441- { "key2" , required_argument , NULL , '2' },
442- { "key3" , required_argument , NULL , '3' },
443- { "key4" , required_argument , NULL , '4' },
444- { "output" , required_argument , NULL , 'o' },
445- { "help" , no_argument , NULL , 'h' },
446- { NULL , 0 , NULL , 0 },
447- };
423+ /* Simple long-option parser (avoids getopt_long portability concerns) */
448424
449- while ((opt = getopt_long (argc , argv , "u:p:i:g:d:o:h" ,
450- g_long_options , NULL )) != -1 )
425+ for (i = 1 ; i < argc ; i ++ )
451426 {
452- switch (opt )
427+ if (strcmp (argv [i ], "--user" ) == 0 && i + 1 < argc )
428+ {
429+ user = argv [++ i ];
430+ }
431+ else if (strcmp (argv [i ], "--password" ) == 0 && i + 1 < argc )
432+ {
433+ password = argv [++ i ];
434+ }
435+ else if (strcmp (argv [i ], "--uid" ) == 0 && i + 1 < argc )
436+ {
437+ uid = atoi (argv [++ i ]);
438+ }
439+ else if (strcmp (argv [i ], "--gid" ) == 0 && i + 1 < argc )
440+ {
441+ gid = atoi (argv [++ i ]);
442+ }
443+ else if (strcmp (argv [i ], "--home" ) == 0 && i + 1 < argc )
444+ {
445+ home = argv [++ i ];
446+ }
447+ else if (strcmp (argv [i ], "--key1" ) == 0 && i + 1 < argc )
448+ {
449+ if (parse_uint32_hex (argv [++ i ], & key [0 ]) < 0 )
450+ {
451+ fprintf (stderr , "mkpasswd: invalid --key1 value: %s\n" , argv [i ]);
452+ return 1 ;
453+ }
454+ }
455+ else if (strcmp (argv [i ], "--key2" ) == 0 && i + 1 < argc )
456+ {
457+ if (parse_uint32_hex (argv [++ i ], & key [1 ]) < 0 )
458+ {
459+ fprintf (stderr , "mkpasswd: invalid --key2 value: %s\n" , argv [i ]);
460+ return 1 ;
461+ }
462+ }
463+ else if (strcmp (argv [i ], "--key3" ) == 0 && i + 1 < argc )
464+ {
465+ if (parse_uint32_hex (argv [++ i ], & key [2 ]) < 0 )
466+ {
467+ fprintf (stderr , "mkpasswd: invalid --key3 value: %s\n" , argv [i ]);
468+ return 1 ;
469+ }
470+ }
471+ else if (strcmp (argv [i ], "--key4" ) == 0 && i + 1 < argc )
472+ {
473+ if (parse_uint32_hex (argv [++ i ], & key [3 ]) < 0 )
474+ {
475+ fprintf (stderr , "mkpasswd: invalid --key4 value: %s\n" , argv [i ]);
476+ return 1 ;
477+ }
478+ }
479+ else if ((strcmp (argv [i ], "-o" ) == 0 ||
480+ strcmp (argv [i ], "--output" ) == 0 ) && i + 1 < argc )
481+ {
482+ outpath = argv [++ i ];
483+ }
484+ else if (strcmp (argv [i ], "--help" ) == 0 ||
485+ strcmp (argv [i ], "-h" ) == 0 )
486+ {
487+ show_usage (argv [0 ]);
488+ return 0 ;
489+ }
490+ else
453491 {
454- case 'u' :
455- user = optarg ;
456- break ;
457-
458- case 'p' :
459- password = optarg ;
460- break ;
461-
462- case 'i' :
463- uid = atoi (optarg );
464- break ;
465-
466- case 'g' :
467- gid = atoi (optarg );
468- break ;
469-
470- case 'd' :
471- home = optarg ;
472- break ;
473-
474- case '1' :
475- if (parse_uint32_hex (optarg , & key [0 ]) < 0 )
476- {
477- fprintf (stderr ,
478- "mkpasswd: invalid --key1 value: %s\n" ,
479- optarg );
480- return 1 ;
481- }
482-
483- break ;
484-
485- case '2' :
486- if (parse_uint32_hex (optarg , & key [1 ]) < 0 )
487- {
488- fprintf (stderr ,
489- "mkpasswd: invalid --key2 value: %s\n" ,
490- optarg );
491- return 1 ;
492- }
493-
494- break ;
495-
496- case '3' :
497- if (parse_uint32_hex (optarg , & key [2 ]) < 0 )
498- {
499- fprintf (stderr ,
500- "mkpasswd: invalid --key3 value: %s\n" ,
501- optarg );
502- return 1 ;
503- }
504-
505- break ;
506-
507- case '4' :
508- if (parse_uint32_hex (optarg , & key [3 ]) < 0 )
509- {
510- fprintf (stderr ,
511- "mkpasswd: invalid --key4 value: %s\n" ,
512- optarg );
513- return 1 ;
514- }
515-
516- break ;
517-
518- case 'o' :
519- outpath = optarg ;
520- break ;
521-
522- case 'h' :
523- show_usage (argv [0 ]);
524- return 0 ;
525-
526- default :
527- show_usage (argv [0 ]);
528- return 1 ;
492+ fprintf (stderr , "mkpasswd: unknown option: %s\n" , argv [i ]);
493+ show_usage (argv [0 ]);
494+ return 1 ;
529495 }
530496 }
531497
@@ -551,6 +517,14 @@ int main(int argc, char **argv)
551517 return 1 ;
552518 }
553519
520+ if (strlen (password ) < MIN_PASSWORD )
521+ {
522+ fprintf (stderr ,
523+ "mkpasswd: --password must be at least %d characters\n" ,
524+ MIN_PASSWORD );
525+ return 1 ;
526+ }
527+
554528 /* Encrypt the password using TEA + custom base64.
555529 * Only the hash is written to the output file; the plaintext is never
556530 * stored in firmware.
0 commit comments